目次 - SDL_mixer 3.0

SDL_mixer 3.0への移行

概要

SDL_mixer 3.0(別名"SDL3_mixer")は以前のバージョンから大きく変わった. APIは完全に再設計された. 互換レイヤは存在しない. このライブラリを使用したいならば, 移行しなければならない.

SDL3_mixerにはSDL3が必要となる. このライブラリは内部と公開されたAPIの両方でSDL3の新しい機能を使用しているため, あなたのプロジェクトがSDL 1.2やSDL2を使用している場合, 同時にそのプロジェクトもSDL3に移行しなければならない.

しかし, 我々はSDL3_mixerとSDL3はどちらも素晴らしいソフトウェア――以前のバージョンから飛躍的に向上した――であり, 一度移行すればその良さをを実感できるはずだ.

単純な置き換えでは移行できない多くの事柄がある. 新しいAPIは多くが, より強力でシンプルになっている. 例えば, Mix_GetNumTracks()と同等の関数は存在しない. 公開されたAPIでMODファイルの内部に関わることを行うのは, 汎用性が低く複雑になるためである.

この移行ガイドでは重要な項目を順に説明するが, 同じ方法で行えない場合もある. 行き詰ったら気軽にバグレポートを開いて欲しい.

ドキュメントの最後の「要約」のセクションには対応するSDL2_mixer関数の名前と短い説明がある.

完全に削除された機能

SDL3_mixerのインクルード

正式なSDL3_mixerヘッダのインクルードの方法は:

#include <SDL3_mixer/SDL_mixer.h>

SDL3と同様に, 新しい方法では<>とサブディレクトリを使用すること.

シンボル名

SDL2_mixerでは, 全ての関数はMix, マクロはMIX_で始まっていた. SDL3_mixerでは, 全てMIX_になった.

バージョン

バージョンは構造体ではなく1つのintにビットが詰められていて, 詰められたビットを戻すにはSDL3の通常の方法を使用する.

初期化

以前のバージョンではMix_Init()を使用するときSDL_mixerにどの形式のファイルを使用するつもりかを伝える必要があった. 現在はその必要はない:

if (!MIX_Init()) {
    SDL_Log("MIX_Init 失敗: %s", SDL_GetError());
} else {
    SDL_Log("SDL_mixerの準備が完了した!");
}

MIX_Init()は参照カウントされているため, 複数回呼んでも安全であり, 実際に初期化されるのは最初の呼び出しのみである. 同様に, MIX_Quit()による実際の終了処理はMIX_Init()と同じ回数が呼ばれた場合のみである. そのため, SDL3_mixerを使用するために初期化するとき, 他の箇所でも初期化しているかを気にする必要はない.

以前のバージョンでは(単一インスタンスの)ミキサーをMix_OpenAudio()でオープンしていたが, このバージョンではMIX_CreateMixerDevice()でオープンする. プログラムの異なる箇所でそれぞれオープンする場合や, 異なるオーディオデバイスを同時に使用する必要がある場合(またはMix_CreateMixer()でデバイスではなくバッファにオーディオを書き込む場合)のため, ミキサーは複数オープンできるようになった.

MIX_CreateMixerDevice()はSDL_AudioSpecをヒントとして受け付けるようになったが, 与えられたあらゆる形式にオーディオデバイスを設定できる保証はない. このヒントは多くの入力が特定の形式であることを示しているだけで, デバイスがその形式を扱うことができれば, 変換の負荷を下げられる可能性がある. しかし, SDL3_mixerは最終的にどのようになる場合でもあらゆる入力と出力の形式を扱えるように備えている.

Mix_QuerySpec()はMIX_GetMixerFormat()に置き換えられた.

ロック

SDL2_mixerは明示的な同期が必要な場合はユーザがSDLオーディオデバイスを直接ロックすることを求めていた. SDL3にはSDL2のSDL_LockAudioDevice()に直接対応する関数はなく, SDL3_mixerではオーディオデバイスを全く操作しない場合があるため, MIX_LockMixer()とMIX_UnlockMixer()API呼び出しが利用できるようになった.

音楽とチャンク

SDL2_mixerは「チャンク」(「チャネル」で再生するためのメモリ上の無圧縮オーディオ)と「音楽」(恐らく圧縮されたストリームオーディオ)を区別され, 1つの音楽の入力と複数のチャンクのミックスが可能だった.

SDL3では, オーディオの種類に区別はなくなり, 全ての入力はあらゆる形式で圧縮または無圧縮, メモリ上またはストリームが可能になった. 必要ならばいくらでもあらゆる種類を一度にミックスできるようになった.

あらかじめ読み込まれた(あらかじめデコードされているとは限らない)オーディオはMIX_Audioオブジェクトとして管理する. これらのオーディオファイルはRAMに事前にキャッシュされ, 事前に, あるいはミキシングの最中に展開される.

SDL2_mixerでは, データをチャンクとして読み込む場合はMix_LoadWAV(), 音楽として読み込む場合はMix_LoadMUS(), またはこれらの派生関数を使用した. SDL3_mixerでは, MIX_LoadAudio()やMIX_LoadAudio_IO(), あるいは一般的でない要求がある場合はMIX_LoadAudioWithProperties()を使用する.

SDL2_mixerの特別な場合の関数Mix_QuickLoad_RAW()は, MIX_LoadRawAudioNoCopy()に置き換えられた. これはわずかに汎用的(データがハードウェアと同じ形式である必要がなくなった)になったが, この関数でも追加のメモリ確保やコピーが行われずに全てのデータがミキシングパイプラインを通過する.

SDL2_mixerの多くの関数は, Mix_FreeChunk()とMix_FreeMusic()のように, チャンク用と音楽用の2種類が用意されていた. SDL3_mixerではその区別がなくなった.

Mix_GetNumChunkDecoders()とMix_GetChunkDecoder()(さらに音楽の同機能の関数)は, MIX_GetNumAudioDecoders()とMIX_GetAudioDecoder()に置き換えられた. 戻される文字列は同じデコードバックエンドでもSDL2_mixerとは異なる場合がある.

チャネル

SDL2_mixerの「チャネル」には, それぞれに1つのチャンクがあり, これが再生でミックスされた. チャネルはインデックス番号で参照され, 使用する予定のチャネルの数は(デフォルトの8でない場合は)Mix_AllocateChannels()であらかじめ確保する必要があった.

SDL3_mixerでは「トラック」になり, それぞれに1つの入力(読み込まれたオーディオファイル, 動的に生成される音声のSDL_AudioStream, ファイルを必要なとき読み込むストリームのSDL_IOStreamなど)がある. これらは1つずつ割り当てられ, MIX_CreateTrack()が戻したポインタから参照される. SDL2_mixerのチャネルと合わせるためにトラックをインデックス化したい場合は, 単にループ内でMIX_CreateTrack()を呼び, ポインタを配列に格納し, その配列のインデックス番号を使用すればよい. デフォルトで生成されるトラックはないため, SDL2_mixerのデフォルトと合わせるためには, 開始時に8つ生成すること.

メタデータ

オーディオファイルのメタデータを戻すMix_GetMusicTitle()のような関数は削除された. その代わりに, 全てのオーディオファイルにSDLプロパティを持たせている.

これらのプロパティには, 低レベルタグ情報と, よく知られたメタデータタイプのための標準プロパティの両方がある. 例えば, ID3v2タグのあるMP3の場合, "SDL_mixer.metadata.id3v2.TIT2"プロパティと, 標準の"SDL_mixer.metadata.title"プロパティ(これには標準のシンボルMIX_PROP_METADATA_TITLE_STRINGがある)は結果的には同じものになる. これによりSDL3_mixerは非標準の情報にアクセスでき, 同時に一般的かつ最も重要なメタデータを簡単に得ることができる.

オーディオファイルを読み込んだ後にMIX_GetAudioProperties()でメタデータを得ることができる(そして, アプリケーション固有のデータを保存する便利な場所にもなる).

フック

SDL3_mixerはミキシングパイプラインのそれぞれの段階でのコールバックを提供している. これでSDL2_mixerのMix_SetPostMix(), Mix_HookMusic(), Mix_HookMusicFinished(), Mix_ChannelFinished(), Mix_RegisterEffect()を再現できる.

SDL3_mixerでは, コールバックには全てのfloat32形式のオーディオデータが提供されるため, 異なる形式のために異なるルーチンを用意する必要がないことに注意すること.

エフェクト

SDL2_mixerにはいくつかの「エフェクト」が内部のコードに組み込まれており, チャンクをミックスの前に編集するためにMix_RegisterEffect()インターフェースを使用した.

Mix_SetPanning()はMIX_SetTrackStereo()に置き換えられるが, サラウンドの場合は強制的に前左と前右スピーカーで再生するトラックに変換される. もし実際にトラックを左右に動かしたいならば, サラウンドのレイアウトを考慮し, MIX_SetTrack3DPosition()を使用してX座標を動かすこと.

Mix_SetPosition()とMix_SetDistance()もMIX_SetTrack3DPosition()を使用するとよりよいが, 角度と距離を3次元座標に変換する必要がある. これは次の数式で行える(未テスト):

const float radians = angle * (SDL_PI_F / 180.0f);  // 弧度法をラジアンに変換する
const float fdistance = ((float) distance);
const float x = SDL_cosf(radians) * fdistance;  // 左から右
const float y = 0.0f;   // 聞き手に対して垂直方向の中央のまま
const float z = SDL_sinf(radians) * fdistance;  // 前から後ろ

Mix_SetReverseStereo()はMIX_SetTrackOutputChannelMap()に置き換えられる:

const int chmap = { 1, 0 };  // 左は右になり, 右は左になる
MIX_SetTrackOutputChannelMap(track, chmap, 2);

チャネルグループ

SDL2_mixerでは, intの値でチャネルを「タグ」付けして, その後でタグと一致する全てのチャネルを参照することができた.

SDL3_mixerでは, 同様にトラックにタグ付けできるが, タグは"ui"や"ambient"のような任意の文字列となった. トラックには複数のタグをつけることができる.

トラックへのタグ付けはMIX_TagTrack()で行い, タグ付けの解除はMIX_UntagTrack()で行う.

再生

SDL2_mixerにはチャネルの再生を開始する複数の関数があった(Mix_Play*, Mix_FadeIn*など). これらは全てMIX_PlayTrack()にまとめられた. MIX_PlayTrack()はオプションとしてSDL_PropertiesIDを取る(デフォルトでは対応できない場合). 再生前に, トラックには事前に読み込まれたオーディオを再生するMIX_SetTrackAudio(), またはファイルを読み込みながら再生するMIX_SetTrackIOStream(), または事前にバッファに書き込んだ, あるいは生成しながら生成したオーディオを再生するMIX_SetTrackAudioStream()で入力が割り当てられている必要がある.

ボリューム

Mix_VolumeChunk()とMix_VolumeMusic()はMIX_SetTrackGain()に置き換えられた. intの0から128に代わりfloatを取るようになり, 既存のデータの音を小さくするだけでなく, より大きくするために使えるようになった.

Mix_MasterVolume()はMIX_SetMixerGain()に置き換えられた. 考え方は同じである.

停止

Mix_HaltChannel(), MIX_HaltMusic(), Mix_FadeOutChannel(), Mix_FadeOutMusic()はMIX_StopTrack()に置き換えられた. 注意: SDL3_mixerでは, フェードアウトはミリ秒ではなくトラックの入力のサンプルフレーム数で動作する. MIX_TrackMSToFrames()でミリ秒をサンプルフレーム数に変換できる. しかし, 複数のトラックを一度に停止させるMIX_StopAllTracks()やMIX_StopTag()はフェードアウトをミリ秒で指定する. 全てのトラックが同じサンプルレートとは限らないためである.

一時停止

Mix_Pause(), Mix_PauseMusic(), Mix_Resume(), Mix_ResumeMusic()はMIX_ResumeTrack()に置き換えられた.

音楽の状態

Mix_MusicDuration()はMIX_GetAudioDuration()に, Mix_GetMusicPosition()はMIX_GetTrackPlaybackPosition()に置き換えられた. Mix_SetMusicPosition()はMIX_SetTrackPlaybackPosition()になった.

終了

Mix_CloseAudio()はMIX_DestroyMixer()になった. ミキサーを破棄すると, それに属する(トラックなど)全てが破棄されるが, MIX_Audioはミキサー間で共有できるため破棄されない. MIX_Quit()は便利のためミキサーとMIX_Audioオブジェクトを含むSDL3_mixerが生成したものを全て破棄する.

要約

SDL2_mixerとの対応と短いコメント

「SDL3_mixerには対応するものはない」ものがあるが, 要望があれば追加される可能性がある. もし行き詰ったならば, イシューに投稿してもらえれば議論できる.

SDL Wikiへのリンク

SDL3_mixer/README-migration