Soundprogrammierung mit Go (Super-Einführungslevel)

Was ich in Nim-Sprache gemacht habe, werde ich in Go-Sprache versuchen. https://qiita.com/mk2/items/bc41f9dfee6669083dbb

Spielen Sie den "do" -Sound

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

Erstellen Sie eine MIDI-Datei (mit Open MIDI Project)

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)

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
	}

}

Quellcode

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

Recommended Posts

Soundprogrammierung mit Go (Super-Einführungslevel)
Asynchrone Programmierung mit libev # 2
3. 3. KI-Programmierung mit Python
Python-Programmierung mit Atom
Wettbewerbsfähige Programmierung mit Python
Shader-Programmierung mit pyOpenGL
Lineare Programmierung mit PuLP
Programmieren mit Python Flask
Asynchrone Programmierung mit libev # 3