What I did in Nim language, I will try it in Go language. https://qiita.com/mk2/items/bc41f9dfee6669083dbb
Use mmsystem.h via cgo. It's Go code, but it's almost like 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("Press Enter to exit...")
reader.ReadString('\n')
}
Using MIDI Data Library provided by Open MIDI Project via cgo I will. DLLs and header files are the same as those used in the Nim language.
This is also almost like 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)
}
Create a MIDI file using gomidi without using cgo.
At first, I was doing the generated MIDI tick with 120 as in the example I did with Open MIDI Project, but when I thought that it was too short and strange, gomidi defaulted to 960 TPQN (how much 1 tick is) It turns out that it seems to generate a MIDI file with a value that determines whether it will be in seconds?).
I was wondering if I could set it to 120TPQN as in the case of Open MIDI Program, but I didn't know the setting, so I changed it so that the same file can be generated with 960TPQN.
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