Was ich in Nim-Sprache gemacht habe, werde ich in Go-Sprache versuchen. https://qiita.com/mk2/items/bc41f9dfee6669083dbb
Verwenden Sie mmsystem.h über cgo. Es ist Go-Code, aber es ist fast wie C.
package main
// #cgo LDFLAGS: -lwinmm
// #include <stdlib.h>
// #include <windows.h>
// #include <mmsystem.h>
import "C"
import (
"bufio"
"fmt"
"math"
"os"
"unsafe"
)
const (
SRATE = 44410
PI = 3.14159286
B_TIME = 1.0
F0 = 440.0
AMP = 40.0
DATA_LEN = int(SRATE * B_TIME)
)
func main() {
var (
hWave C.HWAVEOUT
whdr C.WAVEHDR
wfe C.WAVEFORMATEX
)
bWave := (*[DATA_LEN]byte)(C.malloc(C.ulonglong(DATA_LEN)))
for cnt := 0; cnt < DATA_LEN; cnt++ {
bWave[cnt] = byte(AMP * math.Sin(float64(2.0*PI*F0*float32(cnt)/SRATE)))
}
wfe.wFormatTag = C.WAVE_FORMAT_PCM
wfe.nChannels = 1
wfe.nSamplesPerSec = SRATE
wfe.nAvgBytesPerSec = SRATE
wfe.wBitsPerSample = 8
wfe.nBlockAlign = wfe.nChannels * wfe.wBitsPerSample / 8
C.waveOutOpen(&hWave, C.WAVE_MAPPER, &wfe, 0, 0, C.CALLBACK_NULL)
whdr.lpData = C.LPSTR(unsafe.Pointer(bWave))
whdr.dwBufferLength = C.ulong(DATA_LEN)
whdr.dwFlags = C.WHDR_BEGINLOOP | C.WHDR_ENDLOOP
whdr.dwLoops = 1
C.waveOutPrepareHeader(hWave, &whdr, C.uint(unsafe.Sizeof(C.WAVEHDR{})))
C.waveOutWrite(hWave, &whdr, C.uint(unsafe.Sizeof(C.WAVEHDR{})))
reader := bufio.NewReader(os.Stdin)
fmt.Println("Drücken Sie die Eingabetaste, um den Vorgang zu beenden...")
reader.ReadString('\n')
}
Verwenden von MIDI Data Library, bereitgestellt von Open MIDI Project über cgo Ich werde. Die DLL- und Header-Dateien sind die gleichen wie in der Nim-Sprache.
Dies ist auch fast wie C.
package main
// #cgo windows LDFLAGS: -L. -lMIDIData
// #include "MIDIData.h"
import "C"
func main() {
var midiData = C.MIDIData_Create(C.MIDIDATA_FORMAT0, 1, C.MIDIDATA_TPQNBASE, 120)
var midiTrack = C.MIDIData_GetFirstTrack(midiData)
C.MIDITrack_InsertTrackNameA(midiTrack, 0, C.CString("doremi"))
C.MIDITrack_InsertTempo(midiTrack, 0, 60000000/120)
C.MIDITrack_InsertProgramChange(midiTrack, 0, 0, 1)
C.MIDITrack_InsertNote(midiTrack, 0, 0, 60, 100, 120)
C.MIDITrack_InsertNote(midiTrack, 120, 0, 62, 100, 120)
C.MIDITrack_InsertNote(midiTrack, 240, 0, 64, 100, 120)
C.MIDITrack_InsertEndofTrack(midiTrack, 360)
C.MIDIData_SaveAsSMFA(midiData, C.CString("doremi.midi"))
C.MIDIData_Delete(midiData)
}
Erstellen Sie eine MIDI-Datei mit gomidi, ohne cgo zu verwenden.
Zuerst habe ich den generierten MIDI-Tick mit 120 gemacht, wie im Beispiel mit Open MIDI Project, aber als ich dachte, dass es zu kurz und seltsam ist, hat gomidi standardmäßig 960 TPQN verwendet (wie viel 1 Tick ist). Es stellt sich heraus, dass es eine MIDI-Datei mit einem Wert zu generieren scheint, der bestimmt, ob es in Sekunden sein wird?).
Ich habe mich gefragt, ob ich es wie im Beispiel von Open MIDI Project auf 120TPQN einstellen könnte, aber ich kannte die Einstellung nicht und habe sie so geändert, dass dieselbe Datei mit 960TPQN generiert werden kann.
package main
import (
"fmt"
"os"
"path/filepath"
"gitlab.com/gomidi/midi/writer"
)
func main() {
dir, _ := os.Getwd()
f := filepath.Join(dir, "smf-test.mid")
if _, err := os.Stat(f); os.IsExist(err) {
os.Remove(f)
}
err := writer.WriteSMF(f, 1, func(wr *writer.SMF) error {
writer.TrackSequenceName(wr, "doremi")
writer.TempoBPM(wr, 120)
writer.ProgramChange(wr, 1)
writer.NoteOn(wr, 60, 100)
wr.SetDelta(960)
writer.NoteOff(wr, 60)
writer.NoteOn(wr, 62, 100)
wr.SetDelta(960)
writer.NoteOff(wr, 62)
writer.NoteOn(wr, 64, 100)
wr.SetDelta(960)
writer.NoteOff(wr, 64)
writer.EndOfTrack(wr)
return nil
})
if err != nil {
fmt.Printf("could not write SMF file %v\n", f)
return
}
}
https://github.com/mk2/go-sound-study
Recommended Posts