@@ -46,6 +46,70 @@ class AudioConvert_I16toF32 : public AudioStream_F32 //receive Int and transmits
4646
4747};
4848
49+ class AudioConvert_I16x2toF32 : public AudioStream_F32 // receive Int and transmits Float
50+ {
51+ // GUI: inputs:2, outputs:1 //this line used for automatic generation of GUI node
52+ audio_block_t *inputQueueArray[2 ];
53+
54+ public:
55+ AudioConvert_I16x2toF32 (void )
56+ : AudioStream_F32(0 , nullptr , 2 , inputQueueArray) { };
57+ AudioConvert_I16x2toF32 (const AudioSettings_F32 &settings)
58+ : AudioStream_F32(0 , nullptr , 2 , inputQueueArray) { };
59+
60+ void update (void ) {
61+ // get the Int16 blocks
62+ audio_block_t *int_blockH, *int_blockL;
63+ rxInt16block (int_blockH);
64+ rxInt16block (int_blockL, 1 );
65+
66+ // allocate a float block
67+ audio_block_f32_t *float_block = AudioStream_F32::allocate_f32 ();
68+
69+ // process, as long as we have all blocks
70+ if (nullptr != int_blockH && nullptr != int_blockH && nullptr != float_block)
71+ {
72+ // convert to float
73+ convertAudio_I16x2toF32 (int_blockH, int_blockL, float_block, float_block->length );
74+
75+ // transmit the audio and return it to the system
76+ AudioStream_F32::transmit (float_block,0 );
77+ }
78+ if ( nullptr != float_block) AudioStream_F32::release (float_block);
79+ releaseInt16block (int_blockH);
80+ releaseInt16block (int_blockL);
81+ };
82+
83+ static void convertAudio_I16x2toF32 (audio_block_t *inH, audio_block_t *inL, audio_block_f32_t *out, int len)
84+ {
85+ const float MAX_INT = 32768 .0f *65536 .0f ;
86+ for (int i = 0 ; i < len; i++)
87+ {
88+ // reassemble a 32-bit signed value from two 16-bit values
89+ int32_t sample = ((int32_t ) inH->data [i] << 16 ) | (((int32_t ) inL->data [i]) & 0xFFFF );
90+ out->data [i] = (float )(sample);
91+ }
92+ arm_scale_f32 (out->data , 1.0 /MAX_INT, out->data , out->length ); // divide by 32678*64k to get -1.0 to +1.0
93+ }
94+
95+ // Receive an I16 block, or create a silent one if it's NULL
96+ void rxInt16block (audio_block_t *& blk, unsigned int index = 0 )
97+ {
98+ blk = AudioStream::receiveReadOnly (index);
99+ if (nullptr == blk)
100+ {
101+ blk = AudioStream::allocate ();
102+ if (nullptr != blk)
103+ memset (blk->data , 0 , sizeof blk->data );
104+ }
105+ }
106+
107+ static void releaseInt16block (audio_block_t *& blk)
108+ {
109+ if (nullptr != blk )
110+ AudioStream::release (blk);
111+ }
112+ };
49113
50114class AudioConvert_F32toI16 : public AudioStream_F32 // receive Float and transmits Int
51115{
@@ -88,4 +152,57 @@ class AudioConvert_F32toI16 : public AudioStream_F32 //receive Float and transmi
88152
89153};
90154
155+ class AudioConvert_F32toI16x2 : public AudioStream_F32 // receive Float and transmits Int
156+ {
157+ // GUI: inputs:1, outputs:2 //this line used for automatic generation of GUI node
158+ audio_block_f32_t *inputQueueArray_Float[1 ];
159+ public:
160+ AudioConvert_F32toI16x2 (void ) : AudioStream_F32(1 , inputQueueArray_Float) {};
161+ void update (void ) {
162+ // get the float block
163+ audio_block_f32_t *float_block;
164+ float_block = AudioStream_F32::receiveReadOnly_f32 (); // float data block
165+ if (!float_block) return ;
166+
167+ // allocate a Int16 block
168+ audio_block_t *int_blockH, *int_blockL;
169+ int_blockH = AudioStream::allocate ();
170+ if (int_blockH == NULL )
171+ {
172+ AudioStream_F32::release (float_block);
173+ return ;
174+ }
175+ else
176+ {
177+ int_blockL = AudioStream::allocate ();
178+ if (int_blockL == NULL )
179+ {
180+ AudioStream::release (int_blockH);
181+ AudioStream_F32::release (float_block);
182+ return ;
183+ }
184+ }
185+
186+ // convert back to int16
187+ convertAudio_F32toI16x2 (float_block, int_blockH, int_blockL, float_block->length );
188+
189+ // return audio to the system
190+ AudioStream::transmit (int_blockH);
191+ AudioStream::transmit (int_blockL,1 );
192+ AudioStream::release (int_blockH);
193+ AudioStream::release (int_blockL);
194+ AudioStream_F32::release (float_block);
195+ };
196+
197+ static void convertAudio_F32toI16x2 (audio_block_f32_t *in, audio_block_t *outH, audio_block_t *outL, int len) {
198+ // WEA Method. Should look at CMSIS arm_float_to_q15 instead: https://www.keil.com/pack/doc/CMSIS/DSP/html/group__float__to__x.html#ga215456e35a18db86882e1d3f0d24e1f2
199+ const float MAX_INT = 32678 .0f * 65536 .0f ;
200+ for (int i = 0 ; i < len; i++) {
201+ int32_t intValue = (int32_t )(max (min ( (in->data [i] * MAX_INT), MAX_INT), -MAX_INT));
202+ outH->data [i] = (int16_t ) ((intValue & 0xFFFF0000 )>>16 );
203+ outL->data [i] = (int16_t ) ((intValue & 0x0000FFFF ));
204+ }
205+ }
206+ };
207+
91208#endif
0 commit comments