はあなたが必要となります:リニアPCMオーディオ形式の
はここで何をするかです:
は(Info.plistの中UIFileSharingEnabled=YES
と/Documents
ディレクトリにファイルを書き込む)のアプリでファイル共有を有効にします。
リニアPCMオーディオデータを含むメモリバッファに使用済みサウンドをレンダリングします(まだない場合、つまり圧縮されている場合)。これは、オーディオキューのオフラインレンダリング機能を使用して行うことができます(Apple audio queue docs参照)。同じPCMフォーマットとサンプルレート(例えば16ビットの符号付きサンプル@ 44,100Hz)ですべてをレンダリングすると、ロットが簡単になり、すべてのサンプルでこのフォーマットを使用します。同じフォーマットを使用しますあなたの出力のために。モノフォーマットで始めてから、ステレオを追加することをお勧めします。
は、非圧縮の出力形式を選択して、単一のストリームにあなたのサウンドをミックス:
3.1。十分な大きさのバッファを割り当てるか、または書き込むファイルストリームを開きます。
3.2。最初のサウンドが開始する前に、任意のヘッダーを書き出し(たとえば、未処理のPCMの代わりにWAV形式の出力を使用する場合)、ゼロを書き込んでください(または、サンプルサンプルフォーマットを使用しない場合はサンプル範囲の中間点)例えば、最初のサウンドの前に0.1秒の無音を望む場合は、4410(0.1 * 44100)のゼロサンプルを作成します。つまり、4410の短絡(16ビット)をゼロで書き込みます。
3.3。今、すべての「現在再生中の」サウンドを追跡し、一緒にミックスします。現在再生中のサウンドの空のリストから始め、ミックスしているサンプルの「現在の時間」を追跡します。書き出すサンプルごとに、「現在の時間」をインクリメントするのは1.0/sample_rate
です。別のサウンドが始まる時間が来たら、サンプルオフセットが0の '現在再生中の'リストに追加します。ミキシングを行うには、現在再生中のすべてのサウンドを繰り返し、現在のサンプルを追加します。それぞれのサンプルオフセットをインクリメントします。合計した値を出力バッファに書き込みます。たとえば、soundAが0.1秒(沈黙の後)で、soundBが0.2秒で開始する場合、サンプル8820の場合はoutput[8820] = soundA[4410] + soundB[0];
、サンプル8821の場合はoutput[8821] = soundA[4411] + soundB[1];
に相当します。サウンドが終了すると)現在再生中のリストから削除し、オーディオデータの最後まで続けます。
3.4。上記の単純な混合(サンプルの合計)にはいくつかの問題があります。たとえば、2つのサンプルの値が32767より大きい値を持つ場合、符号付き16ビットの数値に格納することはできません。これはクリッピングと呼ばれます。今のところ、値を32767にクランプして動作させてください...後で戻って単純なリミッタを実装してください(最後の説明を参照)。
あなたのトラックは非圧縮のリニアPCM形式で混在しているので、これで十分かもしれませんので、/Documents
に書き込んでください。圧縮形式で書き込む場合は、オーディオエンコーダのソースを取得し、リニアPCM出力を実行する必要があります。
シンプルリミッター:
絶対値が29490以上であるので、もし我々は値をスケールダウンします(int limitBegin = (int)(32767 * 0.9f);
)、のは、サンプルの範囲の上位10%に制限することを選択しましょう。可能な最大のピークはint maxSampleValue = 32767 * numPlayingSounds;
だろうと、私たちはそれでは、上記の非常にシンプルなミキサーごとにsampleValue
への加算を行う32767でピークにlimitBegin
上記の値をスケールする:
if(sampleValue > limitBegin)
{
float overLimit = (sampleValue - limitBegin)/(float)(maxSampleValue - limitBegin);
sampleValue = limitBegin + (int)(overLimit * (32767 - limitBegin));
}
あなたが注意を払っている場合numPlayingSounds
が変更されたとき(たとえば、新しいサウンドが開始されるときなど)、リミッターがより厳しい(またはそれ以下)になり、余分な音に対応するために突然音量が変更される可能性があります。代わりに最大数の再生音を使用するか、リミッターを数ミリ秒かけてランプアップさせるために賢明な方法を工夫することができます。
絶対値がsampleValue
(符号付きの形式では負の場合もあります)で動作していることを覚えておいてください。サンプル範囲の両端(ピークとトラフ)の制限を処理するには、適切に記述する必要があります。また、ミキシング中に上記のすべてを最適化するためのいくつかのトリックがあります。ミキサーを書いている間にこれらを見つけることができます。注意して最初に働かせ、必要に応じてリファクタリング/最適化してください。
また、使用しているプラットフォームのエンディアンと書き込み先のファイル形式を考慮する必要があります。これは、一部のバイトスワッピングが必要な場合があるためです。
これはできませんか? – c0dec0de