Nim言語で、サウンドプログラミングをします。
初めに
免責
- 筆者はNimプログラミングもサウンドプログラミングもド素人です
環境
- nim 1.2.6 (64bit)
- VC++2019
- Windows限定
この記事のソースコード・dllが含まれるリポジトリ
「ド」の音を再生する
参考書によると、mmsystem.h
というのを読み込んでうまいことコンパイルすれば、Windowsで自由に音が出せるようです。
Nimでは下記のライブラリがmmsystemのラッパーを提供してくれているので利用します(ライブラリ作者の方に感謝 )
nimble install winim
で事前にインストールしておきます。
import math
import winim/inc/mmsystem
const SRATE = 44100
const PI = 3.14159286
proc main() =
var hWave: HWAVEOUT
var whdr: WAVEHDR
var wfe: WAVEFORMATEX
var b_time = 1.0
let data_len = int32(SRATE * b_time)
var bWave: cstring = cast[cstring](alloc0(data_len))
var f0 = 440.0
var amplitude = 40.0
for count in 0..data_len:
bWave[count] = char(amplitude * sin(2 * PI * f0 * float(count) / SRATE))
wfe.wFormatTag = WAVE_FORMAT_PCM
wfe.nChannels = 1
wfe.nSamplesPerSec = SRATE
wfe.nAvgBytesPerSec = SRATE
wfe.wBitsPerSample = 8
wfe.nBlockAlign = uint16(int(wfe.nChannels) * int(wfe.wBitsPerSample) / 8)
waveOutOpen(hWave.addr, WAVE_MAPPER, wfe.addr, 0, 0, CALLBACK_NULL)
whdr.lpData = bWave
whdr.dwBufferLength = data_len
whdr.dwFlags = WHDR_BEGINLOOP or WHDR_ENDLOOP
whdr.dwLoops = 1
waveOutPrepareHeader(hWave, whdr.addr, int32(sizeof(WAVEHDR)))
waveOutWrite(hWave, whdr.addr, int32(sizeof(WAVEHDR)))
echo("終了するには何かキーを押してください:")
discard readLine(stdin)
when isMainModule:
main()
これをnim c -r
で実行すれば、ドの音が流れてきます(音量に注意)。
MIDIファイルを作成する
参考書はおーぷんMIDIぷろじぇくとが提供しているライブラリを利用しているので、それを何とかNimでも利用できるようにします。
必要なファイル
MIDIData.nimはc2nimで作成しました。MIDIData.h
から不要そうなマクロの定義を削除し、api定義のpragmaをいい感じに修正&wchar_tをwinimの定義と合わせる感じで修正を行いました。
MIDIData.dllは配布されているdllが32bitのものだったので、VC++2019で64bitにコンパイルしなおして利用しました。
上記のファイルをダウンロードしたら、ダウンロードした場所に下記のソースコードを作成します。
import winim
import MIDIData
proc main() =
let midiData: ptr MIDIData = MIDIData_Create(MIDIDATA_FORMAT0, 1, MIDIDATA_TPQNBASE, 120)
let midiTrack: ptr MIDITrack = MIDIData_GetFirstTrack(midiData)
MIDITrack_InsertTrackNameW(midiTrack, 0, &T"ドレミ")
MIDITrack_InsertTempo(midiTrack, 0, clong(60000000 / 120))
MIDITrack_InsertProgramChange(midiTrack, 0, 0, 1)
# 音符
MIDITrack_InsertNote(midiTrack, 0, 0, 60, 100, 120) # ド
MIDITrack_InsertNote(midiTrack, 120, 0, 62, 100, 120) # レ
MIDITrack_InsertNote(midiTrack, 240, 0, 64, 100, 120) # ミ
MIDITrack_InsertEndofTrack(midiTrack, 360)
MIDIData_SaveAsSMFW(midiData, &T"doremi.midi")
MIDIData_Delete(midiData)
when isMainModule:
main()
これをnim c -r
で実行すると、doremi.midi
ファイルが作成されます。Windows Media Playerで再生すれば、ピアノ音のドレミを聴くことができます。