Ce que j'ai fait en langue Nim, je vais l'essayer en langue Go. https://qiita.com/mk2/items/bc41f9dfee6669083dbb
Utilisez mmsystem.h via cgo. C'est du code Go, mais c'est presque comme 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("Appuyez sur Entrée pour quitter...")
reader.ReadString('\n')
}
Utilisation de MIDI Data Library fourni par Open MIDI Project via cgo Je vais. La DLL et les fichiers d'en-tête sont les mêmes que ceux utilisés dans le langage Nim.
C'est aussi presque comme 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)
}
Créez un fichier MIDI en utilisant gomidi sans utiliser cgo.
Au début, je faisais le tick MIDI généré avec 120 comme dans l'exemple que j'ai fait avec Open MIDI Project, mais quand je pensais que c'était trop court et étrange, gomidi était par défaut à 960 TPQN (combien 1 tick est) Il s'avère qu'il semble générer un fichier MIDI avec une valeur qui détermine si ce sera en secondes?).
Je me demandais si je pouvais le régler sur 120TPQN comme dans l'exemple d'Open MIDI Project, mais je ne connaissais pas le réglage, alors je l'ai changé pour que le même fichier puisse être généré avec 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