私はサウンドミキサーを実装していますが、SIMD命令を使用しなくてもうまく動作しますが、サウンドデータを別々のチャネルに抽出する方法はわかりません。SIMD命令を使用したオーディオチャネルのデインターリーブ
私のデータはインターリーブ形式になります:L0R0 L1R1 L2R2 L3R3 ... 同じフォーマットで__m128iにロードするので、レジスタに4つのサンプルがあります。
私はそれらを別々のチャンネルにしたいと思います:L0L1L2L3 R0R1R2R3。これは私が紛失している部分です。
入力が8 x i16(4xi32インターリーブ) 出力を左= 4 x f32、右= 4 x f32としたい場合は、混合してください。
に混合した後、私はチャンネルをインターリーブすることができますし、私はL0R0 L1R1 L2R2を取得するには...:
__m128 *src0 = mixed_channel0;
__m128 *src1 = mixed_channel1;
__m128 *dest = (__m128i *)buffer;
for (u32 sample_index = 0; sample_index < sample_chunk_count; ++sample_index)
{
__m128 s0 = _mm_load_ps((f32 *)src0++);
__m128 s1 = _mm_load_ps((f32 *)src1++);
__m128i l = _mm_cvtps_epi32(s0);
__m128i r = _mm_cvtps_epi32(s1);
__m128i lr0 = _mm_unpacklo_epi32(l, r);
__m128i lr1 = _mm_unpackhi_epi32(l, r);
*dest++ = _mm_packs_epi32(lr0, lr1);
}
は基本的に私は反対のことを実行する必要があります。
__m128i input = [L0R0, L1R1, L2R2, L3R3] packed pairs of 16bit ints
// magic happens, then
__m128 left = [L0, L1, L2, L3] packed 32bit floats
__m128 right = [R0, R1, R2, R3] packed 32bit floats
私はマスクしていても低/高位のi16-s、次に私はそれらをf32-sに変換できますか?マスキングアウト後、私はなるだろう:
__m128i right = [xx, R0, xx, R1, xx, R2, xx, R3]
__m128i left = [L0, xx, L1, xx, L2, xx, L3, xx]
私は4×I32-Sに変換することができれば、_mm_cvtepi32_psとF32-Sに変換するのは簡単だろうと私は行われるだろう。
ありがとうございました。
低/高の 'i16'を変換するための最善の策はビットシフトです。 'high_halves = _mm_srai_epi32(packed、16);'。あなたの値が署名されているので、おそらく、左シフトと算術右シフトを使って下半分を符号拡張する必要があります。私はより良い方法のATMを考えることができませんが、これは一種のように見えます。 –
いくつかのSIMD命令セット(ARM NEON/ARMv8など)には、2入力または2出力の命令が2つあります。これを1つの命令で解凍することができます。 (たぶん解凍、IIRC)。だから、SIMDだけでなく、Intel SSEを使って具体的に言うことが重要です。 –
[SSE3](https://blogs.msdn.microsoft.com/chuckw/2012/09/11/directxmath-sse3-and-ssse3/)が必要ですか? SSE/SSE2(https://blogs.msdn.microsoft.com/chuckw/2012/09/11/directxmath-sse-sse2-and-arm-neon/)の方法は「必須」ではありませんが、現代的ですPC、それは非常に一般的です(スティームゲーマーの場合は91%です)。 '' _mm_moveldup_ps''と '' _mm_movehdup_ps''は非常に便利です。 –