目次 - API(機能別) - 再生と録音 - SDL_OpenAudioDevice

# SDL_OpenAudioDevice

指定のオーディオデバイスを開く

## 構文

`SDL_AudioDeviceID SDL_OpenAudioDevice(const char* device, int iscapture, const SDL_AudioSpec* desired, SDL_AudioSpec* obtained, int allowed_changes)`

## 引数

device | SDL_GetAudioDeviceName()で得たUTF-8文字列 (詳細を参照すること)
iscapture | 0でないときデバイスを(再生ではなく)録音として開く
desired | 要求する出力形式のSDL_AudioSpec.詳細はSDL_OpenAudio()を参照すること
obtained | 実際のパラメータが代入されたSDL_AudioSpec.詳細はSDL_OpenAudio()を参照すること
allowed_changes | 0または1つ以上のフラグの論理和 (詳細を参照すること)

## 戻り値

成功のとき0より大きなデバイスIDを戻す. 失敗のとき0を戻す. SDL_GetError()を呼んで詳細を知ることができる.

SDL1.2との互換性のため, この関数が1を戻すことはない. そのIDは古いSDL_OpenAudio()のために予約されている.

## サンプルコード

``

    SDL_AudioSpec want, have;
    SDL_AudioDeviceID dev;

    SDL_memset(&want, 0, sizeof(want)); /* または SDL_zero(want); */
    want.freq = 48000;
    want.format = AUDIO_F32;
    want.channels = 2;
    want.samples = 4096;
    want.callback = MyAudioCallback;  /* この関数はどこか別の場所に書く. 詳細はSDL_AudioSpecを参照すること */

    dev = SDL_OpenAudioDevice(NULL, 0, &want, &have, SDL_AUDIO_ALLOW_FORMAT_CHANGE);
    if (dev == 0) {
        SDL_Log("オーディオを開けなかった: %s", SDL_GetError());
    } else {
        if (have.format != want.format) { /* 要求と変わったか? */
            SDL_Log("32bit浮動小数点のオーディオ形式に対応していない");
        }
        SDL_PauseAudioDevice(dev, 0); /* 再生を開始する */
        SDL_Delay(5000); /* コールバックで音声を5秒間再生する */
        SDL_CloseAudioDevice(dev);
    }

## 詳細

SDL_OpenAudio()はこの関数とは違い, 常にデバイスID 1として振舞う. さらにこの関数は1を戻さないため, 古い関数と衝突することはない.

SDL 2.0.5以前のSDL 2.0は録音に対応していない. よって, iscaptureが0以外のとき, この関数は失敗する. SDL 2.0.5からは録音が実装され, この値を0以外にできる.

deviceをNULLにすると, 最も適したデフォルトを要求したことになる. (そしてそれはSDL_OpenAudio()の選択するデバイスと同じである.) deviceはSDL_GetAudioDeviceName()で得たUTF-8文字列である. しかし一部のドライバは, ホスト名/IPアドレス, またはディスクオーディオドライバのファイル名のような, 定まらないドライバ固有の文字列を要求する.

開いたオーディオデバイスは一時停止の状態から始まる. コールバック関数を呼ぶ準備ができていれば, `SDL_PauseAudioDevice(devid, 0);`を呼んで再生を始める必要がある. オーディオデバイスは要求された音声バッファの長さを変更することがある. オーディオデバイスを開いた後にローカルのミキシングバッファを確保する必要がある.

多くの場合, コールバック関数は別のスレッドで実行される. SDL_LockAudioDevice()で完全に再生を止めなくても, コールバック関数と他のスレッドの競合状態を避けることができる. 詳細はSDL_AudioSpecを参照すること.

要求する音声形式は次のように設定する:

- desired->freq には1秒あたりのサンプル数(Hz)を設定する.
- desired->format には音声形式(AUDIO_S16SYSなど)を設定する.
- desired->samples には音声バッファサイズをサンプルフレーム数(ステレオ出力ならば2サンプル(左右)で1サンプルフレーム)を設定する. この数は2のべき乗である必要があるが, 音声ドライバによってハードウェアにより適した値に調整されることがある. 良い値は512から8096までだが, アプリケーションとCPUの速度による. 値が小さいと遅れが少なくなるが, アプリケーションが重い処理を行うとアンダーフローを引き起こし時間内にバッファを満たせないことがある. サンプルフレーム数と時間の関係は次の式で表される: [ミリ秒] = ([サンプルフレーム数] * 1000) / [サンプル周波数]
- desired->size は音声バッファのバイトサイズだが, SDL_OpenAudioDevice()で計算され, ここでは初期化されない.
- desired->silence は無音の値だが, SDL_OpenAudioDevice()で計算され, ここでは初期化されない.
- desired->callback には音声デバイスが新しいデータの準備ができたとき呼ばれる関数を設定する. その関数には音声バッファのポインタと音声バッファのバイト数が渡される. この関数は通常別のスレッドで実行される. よって, データ構造を保護するため, アクセスするときはSDL_LockAudioDevice()とSDL_UnlockAudioDevice()を呼ぶべきである. この方法の代わりにNULLポインタを渡し, SDL_QueueAudio()を定期的に呼び, 音声をキューに入れる(またはSDL_DequeueAudio()を定期的に呼び, 録音デバイスから音声サンプルを得る)こともできる.
- desired->userdata はコールバック関数の第1引数に渡される. NULLを渡すと, この値は無視される.

allowed_changesは次のフラグの論理和である.

SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | 周波数を変えることを認める
SDL_AUDIO_ALLOW_FORMAT_CHANGE | 形式を変えることを認める
SDL_AUDIO_ALLOW_CHANNELS_CHANGE | チャネル数を変えることを認める
SDL_AUDIO_ALLOW_ANY_CHANGE | 全てを変えることを認める

これらのフラグは, SDLが機能を提供できないとき, どのように振舞うかを決める. アプリケーションが要求した機能をハードウェアが提供できないとき, SDLは常に最も近い機能を獲得しようとする.

例えば, 32bit浮動小数点の音声形式を要求したが, サウンドカードが16bit整数しか対応していない場合, SDLはハードウェアを16bit整数で設定する. もし, SDL_AUDIO_ALLOW_FORMAT_CHANGEを設定していれば, SDLはobtainedのformatフィールドを変更する. もし設定していなければ, コールバック関数で設定した32bit浮動小数点形式のデータを, SDLはハードウェアに送る前に16bit整数形式のデータに変換する. そして, obtainedのformatフィールドは要求と同じである.

結果的に設定された音声形式は, ハードウェアに強く依存し変更される可能性があるが, obtainedに書き込まれる.

アプリケーションが1つの特定の形式しか扱わないのであれば, allowed_changesを0として, SDLに他の形式に変換させることができる.

## バージョン

SDL 2.0.0以降

## 関連項目(関数)

SDL_CloseAudioDevice
SDL_GetAudioDeviceName
SDL_LockAudioDevice
SDL_OpenAudio
SDL_PauseAudioDevice
SDL_UnlockAudioDevice

## SDL Wikiへのリンク

SDL_OpenAudioDevice - SDL Wiki