6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Nimでサウンドプログラミング(超入門レベル)

Posted at

Nim言語で、サウンドプログラミングをします。

初めに

免責

  • 筆者はNimプログラミングもサウンドプログラミングもド素人です

環境

  • nim 1.2.6 (64bit)
  • VC++2019
  • Windows限定

この記事のソースコード・dllが含まれるリポジトリ

「ド」の音を再生する

参考書によると、mmsystem.hというのを読み込んでうまいことコンパイルすれば、Windowsで自由に音が出せるようです。

Nimでは下記のライブラリがmmsystemのラッパーを提供してくれているので利用します(ライブラリ作者の方に感謝 :pray:

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で再生すれば、ピアノ音のドレミを聴くことができます。

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?