Programmation sonore avec Go (super niveau d'introduction)

Ce que j'ai fait en langue Nim, je vais l'essayer en langue Go. https://qiita.com/mk2/items/bc41f9dfee6669083dbb

Jouez le son "do"

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')
}

Créez un fichier MIDI (en utilisant Open MIDI Project)

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)

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
	}

}

Code source

https://github.com/mk2/go-sound-study

Recommended Posts

Programmation sonore avec Go (super niveau d'introduction)
Programmation asynchrone avec libev # 2
3. 3. Programmation IA avec Python
Programmation Python avec Atom
Programmation compétitive avec python
Programmation Shader avec pyOpenGL
Programmation linéaire avec PuLP
Programmation avec Python Flask
Programmation asynchrone avec libev # 3