Win版 MIDIファイルからテンポが正しく読み取れていない
メタイベントクラスのテンポ取得メソッド(SMEventMeta::GetTempo)の不具合。 初回リリース時からの潜在不具合である。
標準MIDIファイルから読み取ったテンポのデータは3byteで、四分音符の長さ(マイクロ秒)を示す。 当該メソッドでは、3byteのデータを数値に変換する際に、下位1byteを3byte目からではなく4byte目から読み取っていた。 4byte目はゼロクリアされているバッファ領域のため、テンポの下位1byteを常にゼロとして数値変換していた。
例えばBPM 94の場合、四分音符の長さは638297マイクロ秒であり、16進数に変換すると0x09BD59。 標準MIDIファイルに記録されているテンポのデータは 09 BD 59 の3byteとなる。 しかし当該不具合により、読み取ったテンポは0x09BD00となり、638208マイクロ秒と解釈することになった(偏差は-89マイクロ秒)。 この場合、四分音符の長さに0.014%の誤差が生じてしまう。
BPMの値が大きいほど(演奏速度が早いほど)、四分音符の長さの値は小さくなるため、 テンポの下位1byteがゼロになる影響はより大きくなる。 例えばBPM 204では下位1byte0xE5が0x00となり、誤差は0.078%になる。
macOS版、iOS版にも同じの不具合がある。
テンポの下位1byteを3byte目から取得するように修正する。
修正前 tempo = (pData[0] << 16) | (pData[1] << 8) | (pData[3]); 修正後 tempo = (pData[0] << 16) | (pData[1] << 8) | (pData[2]);
DominoやSekaijuのMIDI編集ソフトとMIDITrailで、同じMIDIデータ(DAISEI92.MID)を再生して録音し、 サウンド編集ソフトで波形を並べて比較したところ、MIDITrailの演奏時間が0.05秒ほど短いことが分かった。