Nusedriver lite manual
Index
- Overview
- Features
- NoteLength
- NoteScale
- NoteVelocity
- NoiseVoice
-
MusicProgram
- $00-$0F ControlChange
- $00 Tempo
- $01 GateTime
- $02 ReleaseTime
- $03 DataEntry
- $04 VolumeEnvelopeAttack
- $05 VolumeEnvelopeRelease
- $06 DutyEnvelopeAttack
- $07 DutyEnvelopeRelease
- $08 PitchEnvelope
- $09 PitchEnvelopeDelay
- $0A NoteEnvelopeAbsolute
- $0B NoteEnvelopeRelative
- $0C JumpWithRepeat
- $0D ReturnFromJump
- $0E JumpToMacro
- $0F ReturnFromMacro
- Envelope
- $10-$1F PerformanceChange
- $10 PermanentNoteLength0
- $11 PermanentNoteLength1
- $12 PermanentNoteLength2
- $13 PermanentNoteLength3
- $14 PermanentNoteRootAbsolute
- $15 PermanentNoteRootRelative
- $16 PermanentNoteScale
- $17 PermanentNoteVelocity
- $18 TemporaryNoteLength0
- $19 TemporaryNoteLength1
- $1A TemporaryNoteLength2
- $1B TemporaryNoteLength3
- $1C TemporaryNoteRootPlus1
- $1D TemporaryNoteRootPlus12
- $1E TemporaryNoteRootMinus1
- $1F TemporaryNoteRootMinus12
- $20-$FF Note
Nusedriver liteは、Nurv Cockymanが開発したファミコン用サウンドドライバ。
Nusedriver_20210717_r1をベースとして、音符情報1つを1Byteに収める為の設計変更・実装を施したもの。
以下のテーマについて、バランスを取りつつ追及していきたい。
- ソフトウェアならではの演奏方法
- 音楽的表現力
- ファミコンのハードウェアリソース
アセンブルにはnesasm_x64.exeを使用する。
将来的にゲームに組み込んで使用したい。
実機での動作確認は未実施。
効果音に関しては未実装。
DPCMは使用しない。
拡張音源は使用しない。
NoteLength
音符の長さは2Byteで表現される。
1frame毎にnote_lengthからbpm値が減算され、0以下になったら次の音符を読み込む。
note_lengthが負の数となってしまっても自動で補正される為、frameのガタツキについてユーザが意識する必要は無い。
NoteLengthはtableになっており、16Byte/1set、最大4set登録出来る。
4setの内訳は、normal, detted(付点), triplet(3連符), user_defined。
音符毎にindex(1-7) 7段階を指定する。
| index: | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| normal: | 450 | 900 | 1800 | 3600 | 7200 | 14400 | 28800 |
| detted: | 675 | 1350 | 2700 | 5400 | 10800 | 21600 | 43200 |
| triplet: | 150 | 300 | 600 | 1200 | 2400 | 4800 | 9600 |
NoteScale
1音符1Byteを実現する上で最も重要な機能・概念。
Rootとなる音階からの差によって音階の高低を表現する。
1つのNote Scaleは、Rootからの差分8個からなる。
音符毎にindex(0-7) 8段階を指定する。
| index: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| major_scale: | $00 | $02 | $04 | $05 | $07 | $09 | $0B | $0C |
| minor_scale: | $00 | $02 | $03 | $05 | $07 | $08 | $0A | $0C |
index 0-7それぞれに、Rootからの差分(単位は半音階)が定義される。
NoteScaleは最大32個登録することが出来る。
PermanentNoteScaleによって曲中で切り替えることが可能。
NoteVelocity
音符毎に4段階(0-3)の強弱がつけられる。
NoteVelocityはtableになっており、64Byte/1set、最大4set登録出来る。
PermanentNoteVelocityによって曲中で切り替えることが可能。
1setの内容は、16Byte * 強弱4段階。
この16ByteはVolumeEnvelopeと関連している。
ex.下記条件の場合、.db 3行目の12番目である$08が最終的なchannel_volumeとなる。
note_velocity = 2
volume_envelope_decoded_data = 12
NOTE_VELOCITY_TABLE:
.note_velocity_0
.db $00,$00,$00,$00,$00,$00,$00,$00,$01,$01,$01,$01,$01,$01,$01,$01 ; note_velocity = 0
.db $00,$01,$01,$01,$02,$02,$02,$03,$03,$03,$04,$04,$04,$05,$05,$05 ; note_velocity = 1
.db $00,$01,$02,$02,$03,$04,$04,$05,$05,$06,$07,$07,$08,$09,$09,$0A ; note_velocity = 2
.db $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$0A,$0B,$0C,$0D,$0E,$0F ; note_velocity = 3
NoiseVoice
Noise channelは登録済みVoiceを呼び出して鳴らす形となる。
NoiseVoiceは、VolumeEnvelopeAttackとPitchEnvelopeから構成される。
Noise channel向けPitchEnvelopeは他のchannelとは違い、周波数の相対変化ではなく、$400Eレジスタに書き込む値そのものである。
Others
その他、特徴的な機能として、NoteEnvelopeAbsolute, PitchEnvelopeDelay, VolumeLimitter等がある。
MusicProgram
曲データは、Nusedriver lite独自のMusicProgramによって記述する。
MusicProgramは、ControlChange, PerformanceChange, Noteの3種に大別される。
音色の変更や曲の進行に関する変更を担う。
- $00 Tempo
-
- bpm (1~255)
Beats per Minuteを指定する。
全channelでひとつの変数を共有している。
0だと曲が進行しない。
ex. BPMを150にしたい場合
.db CcTempo,150
- $01 GateTime
-
- note_gate_time lo
- note_gate_time hi
note_gate_timeを指定する。
Note前方から数えてnote_gate_time分、NoteのReleaseが早まる。
スタッカートのような使い方を想定。
ex. GateTimeを16分音符分にしたい場合
.db CcGateTime
.dw WHOLE_NOTE_LENGTH/16
- $02 ReleaseTime
-
- note_release_time lo
- note_release_time hi
note_release_timeを指定する。
Note後方から数えてnote_release_time分、NoteのReleaseが早まる。
ex. ReleaseTimeを4分音符分にしたい場合
.db CcReleaseTime
.dw WHOLE_NOTE_LENGTH/4
- $03 DataEntry
-
- address lo
- address hi
- value
addressの番地にvalueを書き込む。
channelは自動的に判別される。
pitch_detuneやchannel_volume_limitter等、1Byteの変数に対して使用する。
ex. channel_volume_limitterに8を入れたい場合
.db CcDataEntry
.dw channel_volume_limitter
.db 8
- $04 VolumeEnvelopeAttack
-
- volume_envelope_attack_address lo
- volume_envelope_attack_address hi
Attack用VolumeEnvelopeのLabel Addressを指定する。
Label以降の記述で、volume_envelope値として使用可能な範囲は0~15.
ex. Attack用VolumeEnvelopeを指定する場合
.db CcVolumeEnvelopeAttack
.dw .volume_attack
.volume_attack
.db Literal+3,$07,$0A,$0D,Fill+127,$0F,JumpTo,-2
- $05 VolumeEnvelopeRelease
-
- volume_envelope_release_address lo
- volume_envelope_release_address hi
Release用VolumeEnvelopeのLabel Addressを指定する。
Label以降の記述で、volume_envelope値として使用可能な範囲は0~15.
ex. Release用VolumeEnvelopeを指定する場合
.db CcVolumeEnvelopeAttack
.dw .volume_release
.volume_release
.db Fill+127,$02,JumpTo,-2
- $06 DutyEnvelopeAttack
-
- duty_envelope_attack_address lo
- duty_envelope_attack_address hi
Attack用DutyEnvelopeのLabel Addressを指定する。
Label以降の記述で、duty_envelope値として使用可能な範囲は0~3.
ex. Attack用DutyEnvelopeを指定する場合
.db CcDutyEnvelopeAttack
.dw .duty_attack
.duty_attack
.db Fill+3,$01,Fill+127,$02,JumpTo,-2
- $07 DutyEnvelopeRelease
-
- duty_envelope_release_address lo
- duty_envelope_release_address hi
Release用DutyEnvelopeのLabel Addressを指定する。
Label以降の記述で、duty_envelope値として使用可能な範囲は0~3.
ex. Release用DutyEnvelopeを指定する場合
.db CcDutyEnvelopeRelease
.dw .duty_release
.duty_release
.db Fill+127,$03,JumpTo,-2
- $08 PitchEnvelope
-
- pitch_envelope_address lo
- pitch_envelope_address hi
PitchEnvelopeのLabel Addressを指定する。
Label以降の記述で、pitch_envelope値として使用可能な範囲は-128~127.
正の値だと周波数が下がり、負の値だと周波数が上がることに注意。
ex. PitchEnvelopeを指定する場合
.db CcPitchEnvelope
.dw .pitch
.pitch
.db Literal+1,-1,Fill+2,0,Literal+1,-1,Fill+2,0,Literal+1,1,Fill+2,0,Literal+1,1,Fill+2,0,JumpTo,-16
- $09 PitchEnvelopeDelay
-
- pitch_envelope_delay_time lo
- pitch_envelope_delay_time hi
pitch_envelope_delay_timeを指定する。
NoteOn以降、pitch_envelope_delay_time分、PitchEnvelopeの開始を遅延できる。
ex. PitchEnvelopeの開始を付点4分音符分遅延させる場合
.db CcPitchEnvelopeDelay
.dw WHOLE_NOTE_LENGTH/2*3/4
- $0A NoteEnvelopeAbsolute
-
- note_envelope_absolute_address lo
- note_envelope_absolute_address hi
絶対NoteEnvelopeのLabel Addressを指定する。
NoteTranspose, PitchEnvelope, PitchDetuneと併用可能。
NoteEnvelopeRelativeとは排他制御であり、NoteEnvelopeAbsolute読込み時にNoteEnvelopeRelative無効となる。
Label以降の記述で、note_envelope値として使用可能な範囲は33~127.
note_envelope値として0を指定すると、NoteOn時のNoteNumberで周波数設定される。
ex. 絶対NoteEnvelopeを指定する場合(Noteの先頭のみKick、その後にBass音を鳴らす)
.db CcNoteEnvelopeAbsolute
.dw note_absolute
.note_absolute
.db Literal+8,72,64,56,52,48,44,40,36,Fill+127,0,JumpTo,-2
- $0B NoteEnvelopeRelative
-
- note_envelope_relative_address lo
- note_envelope_relative_address hi
相対NoteEnvelopeのLabel Addressを指定する。
NoteTranspose, PitchEnvelope, PitchDetuneと併用可能。
NoteEnvelopeAbsoluteとは排他制御であり、NoteEnvelopeRelative読込み時にNoteEnvelopeAbsolute無効となる。
Label以降の記述で、note_envelope値として使用可能な範囲は-95~95.
note_envelope値は、NoteOn時のNoteNumberに対し相対指定する。
ex. 相対NoteEnvelopeを指定する場合(NoteOn時のNoteNumberをroot音としてmaj7を鳴らす)
.db CcNoteEnvelopeRelative
.dw note_relative
.note_relative
.db Literal+6,0,4,7,11,7,4,JumpTo,-7
- $0C JumpWithRepeat
-
- jump_with_repeat_address lo
- jump_with_repeat_address hi
- jump_repetition (1-255)
Jump先のLabel Addressと繰返し回数を指定する。
Jump先でReturnFromJumpが実行される毎にjump_repetitionが減算され、0になるとJump元に戻る。
無限ループにしたい場合はReturnFromJumpを実効しなければ良い。
ex. 同じフレーズを2回繰返す場合
.db CcJumpWithRepeat
.dw .riff
.db 2
.riff
.db %01101010,%01101010,%01101010,%01101010,%01101010,%01101010,%01100010,%01100010,CcReturnFromJump
- $0D ReturnFromJump
-
no operand
JumpWithRepeat参照
- $0E JumpToMacro
-
- music_macro_table_number (0-127)
Jump先のmusic_macro_table_numberを指定する。
- $0F ReturnFromMacro
-
no operand
Jump元に戻る。
Switched Run Length Encoding
Envelopeの記述方法としてSwitched Run Length Encodingを参考にして実装した。
(一般的なSwitched Run Length Encodingとは異なると思われる)
先頭の1Byteでmode(Literal(不連続) or Fill(連続))とlength(modeの対象となるByte数)を指定する。
modeは7bit目で識別される。
下記のように定義されており、ex.に示すように記述することで視認性が上がる。
Literal = 0
Fill = $80
JumpTo
JumpTo = $80で定義してあり、続く1ByteでJump先のアドレスを相対指定できる。(正の値も指定可能)
ただし、Jump先及びEncoded Data長は、EnvelopeのLabel Addressから255Byteまでの範囲におさめる必要がある。
ex. 0,1,2,5,5,5,5,0,1,2,5,5,5,0,1,2...
.encoded_data
.db Literal+3,0,1,2,Fill+4,5,JumpTo,-6
演奏方法に関する変更を担う。
効果が永続的なPermanentと、次のNoteのみに適用となるTemporaryの2つに大別される。
$10 PermanentNoteLength0
no operand
永続的にlength_table指定を変更出来る。
0番目(normal)のlength_tableが指定される。
$11 PermanentNoteLength1
no operand
永続的にlength_table指定を変更出来る。
1番目(dotted(付点))のlength_tableが指定される。
$12 PermanentNoteLength2
no operand
永続的にlength_table指定を変更出来る。
2番目(triplet(3連符))のlength_tableが指定される。
$13 PermanentNoteLength3
no operand
永続的にlength_table指定を変更出来る。
3番目(user_defined)のlength_tableが指定される。
ex.
.db
$14 PermanentNoteRootAbsolute
- note_number
永続的にRoot音を変更出来る。
(絶対指定)
ex.
.db
$15 PermanentNoteRootRelative
- transpose_value
永続的にRoot音を変更出来る。
(以前のRoot音からの相対指定)
ex.
.db
$16 PermanentNoteScale
- note_scale_table_number (0-31)
永続的にnote_scale_tableを変更出来る。
ex.
.db
$17 PermanentNoteVelocity
- note_velocity_table_number (0-3)
永続的にnote_velocity_tableを変更出来る。
ex.
.db
$18 TemporaryNoteLength0
no operand
このCommandの次に現れるNoteのみ一時的にlength_table指定を変更出来る。
0番目(normal)のlength_tableが指定される。
$19 TemporaryNoteLength1
no operand
このCommandの次に現れるNoteのみ一時的にlength_table指定を変更出来る。
1番目(dotted(付点))のlength_tableが指定される。
$1A TemporaryNoteLength2
no operand
このCommandの次に現れるNoteのみ一時的にlength_table指定を変更出来る。
2番目(triplet(3連符))のlength_tableが指定される。
$1B TemporaryNoteLength3
no operand
このCommandの次に現れるNoteのみ一時的にlength_table指定を変更出来る。
3番目(user_defined)のlength_tableが指定される。
ex.
.db
$1C TemporaryNoteRootPlus1
no operand
このCommandの次に現れるNoteのみ一時的にRoot音を変更出来る。
Plus1なので半音上がる。
ex.
.db
$1D TemporaryNoteRootPlus12
no operand
このCommandの次に現れるNoteのみ一時的にRoot音を変更出来る。
Plus12なので1オクターブ上がる。
ex.
.db
$1E TemporaryNoteRootMinus1
no operand
このCommandの次に現れるNoteのみ一時的にRoot音を変更出来る。
Minus1なので半音下がる。
ex.
.db
$1F TemporaryNoteRootMinus12
no operand
このCommandの次に現れるNoteのみ一時的にRoot音を変更出来る。
Minus12なので1オクターブ下がる。
ex.
.db
- $20-$FF Note Info (%lllsssvv)
-
- l = length (1-7)
- s = scale (0-7)
- v = velocity (0-3)