@@ -86,15 +86,15 @@ void AudioStreamPlaybackWAV::seek(double p_time) {
8686 offset = uint64_t (p_time * base->mix_rate ) << MIX_FRAC_BITS;
8787}
8888
89- template <typename Depth, bool is_stereo, bool is_ima_adpcm>
90- void AudioStreamPlaybackWAV::do_resample (const Depth *p_src, AudioFrame *p_dst, int64_t &p_offset, int32_t &p_increment, uint32_t p_amount, IMA_ADPCM_State *p_ima_adpcm) {
89+ template <typename Depth, bool is_stereo, bool is_ima_adpcm, bool is_qoa >
90+ void AudioStreamPlaybackWAV::do_resample (const Depth *p_src, AudioFrame *p_dst, int64_t &p_offset, int32_t &p_increment, uint32_t p_amount, IMA_ADPCM_State *p_ima_adpcm, QOA_State *p_qoa ) {
9191 // this function will be compiled branchless by any decent compiler
9292
93- int32_t final , final_r, next, next_r;
93+ int32_t final = 0 , final_r = 0 , next = 0 , next_r = 0 ;
9494 while (p_amount) {
9595 p_amount--;
9696 int64_t pos = p_offset >> MIX_FRAC_BITS;
97- if (is_stereo && !is_ima_adpcm) {
97+ if (is_stereo && !is_ima_adpcm && !is_qoa ) {
9898 pos <<= 1 ;
9999 }
100100
@@ -175,32 +175,77 @@ void AudioStreamPlaybackWAV::do_resample(const Depth *p_src, AudioFrame *p_dst,
175175 }
176176
177177 } else {
178- final = p_src[pos];
179- if (is_stereo) {
180- final_r = p_src[pos + 1 ];
181- }
178+ if (is_qoa) {
179+ if (pos != p_qoa->cache_pos ) { // Prevents triple decoding on lower mix rates.
180+ for (int i = 0 ; i < 2 ; i++) {
181+ // Sign operations prevent triple decoding on backward loops, maxing prevents pop.
182+ uint32_t interp_pos = MIN (pos + (i * sign) + (sign < 0 ), p_qoa->desc ->samples - 1 );
183+ uint32_t new_data_ofs = 8 + interp_pos / QOA_FRAME_LEN * p_qoa->frame_len ;
184+
185+ if (p_qoa->data_ofs != new_data_ofs) {
186+ p_qoa->data_ofs = new_data_ofs;
187+ const uint8_t *src_ptr = (const uint8_t *)base->data ;
188+ src_ptr += p_qoa->data_ofs + AudioStreamWAV::DATA_PAD;
189+ qoa_decode_frame (src_ptr, p_qoa->frame_len , p_qoa->desc , p_qoa->dec , &p_qoa->dec_len );
190+ }
182191
183- if constexpr (sizeof (Depth) == 1 ) { /* conditions will not exist anymore when compiled! */
184- final <<= 8 ;
192+ uint32_t dec_idx = (interp_pos % QOA_FRAME_LEN) * p_qoa->desc ->channels ;
193+
194+ if ((sign > 0 && i == 0 ) || (sign < 0 && i == 1 )) {
195+ final = p_qoa->dec [dec_idx];
196+ p_qoa->cache [0 ] = final ;
197+ if (is_stereo) {
198+ final_r = p_qoa->dec [dec_idx + 1 ];
199+ p_qoa->cache_r [0 ] = final_r;
200+ }
201+ } else {
202+ next = p_qoa->dec [dec_idx];
203+ p_qoa->cache [1 ] = next;
204+ if (is_stereo) {
205+ next_r = p_qoa->dec [dec_idx + 1 ];
206+ p_qoa->cache_r [1 ] = next_r;
207+ }
208+ }
209+ }
210+ p_qoa->cache_pos = pos;
211+ } else {
212+ final = p_qoa->cache [0 ];
213+ if (is_stereo) {
214+ final_r = p_qoa->cache_r [0 ];
215+ }
216+
217+ next = p_qoa->cache [1 ];
218+ if (is_stereo) {
219+ next_r = p_qoa->cache_r [1 ];
220+ }
221+ }
222+ } else {
223+ final = p_src[pos];
185224 if (is_stereo) {
186- final_r <<= 8 ;
225+ final_r = p_src[pos + 1 ] ;
187226 }
188- }
189227
190- if (is_stereo) {
191- next = p_src[pos + 2 ] ;
192- next_r = p_src[pos + 3 ];
193- } else {
194- next = p_src[pos + 1 ];
195- }
228+ if constexpr ( sizeof (Depth) == 1 ) { /* conditions will not exist anymore when compiled! */
229+ final <<= 8 ;
230+ if (is_stereo) {
231+ final_r <<= 8 ;
232+ }
233+ }
196234
197- if constexpr (sizeof (Depth) == 1 ) {
198- next <<= 8 ;
199235 if (is_stereo) {
200- next_r <<= 8 ;
236+ next = p_src[pos + 2 ];
237+ next_r = p_src[pos + 3 ];
238+ } else {
239+ next = p_src[pos + 1 ];
201240 }
202- }
203241
242+ if constexpr (sizeof (Depth) == 1 ) {
243+ next <<= 8 ;
244+ if (is_stereo) {
245+ next_r <<= 8 ;
246+ }
247+ }
248+ }
204249 int32_t frac = int64_t (p_offset & MIX_FRAC_MASK);
205250
206251 final = final + ((next - final ) * frac >> MIX_FRAC_BITS);
@@ -240,6 +285,9 @@ int AudioStreamPlaybackWAV::mix(AudioFrame *p_buffer, float p_rate_scale, int p_
240285 case AudioStreamWAV::FORMAT_IMA_ADPCM:
241286 len *= 2 ;
242287 break ;
288+ case AudioStreamWAV::FORMAT_QOA:
289+ len = qoa.desc ->samples * qoa.desc ->channels ;
290+ break ;
243291 }
244292
245293 if (base->stereo ) {
@@ -368,27 +416,34 @@ int AudioStreamPlaybackWAV::mix(AudioFrame *p_buffer, float p_rate_scale, int p_
368416 switch (base->format ) {
369417 case AudioStreamWAV::FORMAT_8_BITS: {
370418 if (is_stereo) {
371- do_resample<int8_t , true , false >((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm);
419+ do_resample<int8_t , true , false , false >((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm, &qoa );
372420 } else {
373- do_resample<int8_t , false , false >((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm);
421+ do_resample<int8_t , false , false , false >((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm, &qoa );
374422 }
375423 } break ;
376424 case AudioStreamWAV::FORMAT_16_BITS: {
377425 if (is_stereo) {
378- do_resample<int16_t , true , false >((int16_t *)data, dst_buff, offset, increment, target, ima_adpcm);
426+ do_resample<int16_t , true , false , false >((int16_t *)data, dst_buff, offset, increment, target, ima_adpcm, &qoa );
379427 } else {
380- do_resample<int16_t , false , false >((int16_t *)data, dst_buff, offset, increment, target, ima_adpcm);
428+ do_resample<int16_t , false , false , false >((int16_t *)data, dst_buff, offset, increment, target, ima_adpcm, &qoa );
381429 }
382430
383431 } break ;
384432 case AudioStreamWAV::FORMAT_IMA_ADPCM: {
385433 if (is_stereo) {
386- do_resample<int8_t , true , true >((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm);
434+ do_resample<int8_t , true , true , false >((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm, &qoa );
387435 } else {
388- do_resample<int8_t , false , true >((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm);
436+ do_resample<int8_t , false , true , false >((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm, &qoa );
389437 }
390438
391439 } break ;
440+ case AudioStreamWAV::FORMAT_QOA: {
441+ if (is_stereo) {
442+ do_resample<uint8_t , true , false , true >((uint8_t *)data, dst_buff, offset, increment, target, ima_adpcm, &qoa);
443+ } else {
444+ do_resample<uint8_t , false , false , true >((uint8_t *)data, dst_buff, offset, increment, target, ima_adpcm, &qoa);
445+ }
446+ } break ;
392447 }
393448
394449 dst_buff += target;
@@ -412,6 +467,16 @@ void AudioStreamPlaybackWAV::tag_used_streams() {
412467
413468AudioStreamPlaybackWAV::AudioStreamPlaybackWAV () {}
414469
470+ AudioStreamPlaybackWAV::~AudioStreamPlaybackWAV () {
471+ if (qoa.desc ) {
472+ memfree (qoa.desc );
473+ }
474+
475+ if (qoa.dec ) {
476+ memfree (qoa.dec );
477+ }
478+ }
479+
415480// ///////////////////
416481
417482void AudioStreamWAV::set_format (Format p_format) {
@@ -475,6 +540,10 @@ double AudioStreamWAV::get_length() const {
475540 case AudioStreamWAV::FORMAT_IMA_ADPCM:
476541 len *= 2 ;
477542 break ;
543+ case AudioStreamWAV::FORMAT_QOA:
544+ qoa_desc desc = { 0 , 0 , 0 , { { { 0 }, { 0 } } } };
545+ qoa_decode_header ((uint8_t *)data + DATA_PAD, QOA_MIN_FILESIZE, &desc);
546+ len = desc.samples * desc.channels ;
478547 }
479548
480549 if (stereo) {
@@ -526,8 +595,8 @@ Vector<uint8_t> AudioStreamWAV::get_data() const {
526595}
527596
528597Error AudioStreamWAV::save_to_wav (const String &p_path) {
529- if (format == AudioStreamWAV::FORMAT_IMA_ADPCM) {
530- WARN_PRINT (" Saving IMA_ADPC samples are not supported yet" );
598+ if (format == AudioStreamWAV::FORMAT_IMA_ADPCM || format == AudioStreamWAV::FORMAT_QOA ) {
599+ WARN_PRINT (" Saving IMA_ADPCM and QOA samples is not supported yet" );
531600 return ERR_UNAVAILABLE;
532601 }
533602
@@ -548,6 +617,7 @@ Error AudioStreamWAV::save_to_wav(const String &p_path) {
548617 byte_pr_sample = 1 ;
549618 break ;
550619 case AudioStreamWAV::FORMAT_16_BITS:
620+ case AudioStreamWAV::FORMAT_QOA:
551621 byte_pr_sample = 2 ;
552622 break ;
553623 case AudioStreamWAV::FORMAT_IMA_ADPCM:
@@ -590,6 +660,7 @@ Error AudioStreamWAV::save_to_wav(const String &p_path) {
590660 }
591661 break ;
592662 case AudioStreamWAV::FORMAT_16_BITS:
663+ case AudioStreamWAV::FORMAT_QOA:
593664 for (unsigned int i = 0 ; i < data_bytes / 2 ; i++) {
594665 uint16_t data_point = decode_uint16 (&read_data[i * 2 ]);
595666 file->store_16 (data_point);
@@ -607,6 +678,16 @@ Ref<AudioStreamPlayback> AudioStreamWAV::instantiate_playback() {
607678 Ref<AudioStreamPlaybackWAV> sample;
608679 sample.instantiate ();
609680 sample->base = Ref<AudioStreamWAV>(this );
681+
682+ if (format == AudioStreamWAV::FORMAT_QOA) {
683+ sample->qoa .desc = (qoa_desc *)memalloc (sizeof (qoa_desc));
684+ qoa_decode_header ((uint8_t *)data + DATA_PAD, QOA_MIN_FILESIZE, sample->qoa .desc );
685+ sample->qoa .frame_len = qoa_max_frame_size (sample->qoa .desc );
686+ int samples_len = (sample->qoa .desc ->samples > QOA_FRAME_LEN ? QOA_FRAME_LEN : sample->qoa .desc ->samples );
687+ int alloc_len = sample->qoa .desc ->channels * samples_len * sizeof (int16_t );
688+ sample->qoa .dec = (int16_t *)memalloc (alloc_len);
689+ }
690+
610691 return sample;
611692}
612693
@@ -639,7 +720,7 @@ void AudioStreamWAV::_bind_methods() {
639720 ClassDB::bind_method (D_METHOD (" save_to_wav" , " path" ), &AudioStreamWAV::save_to_wav);
640721
641722 ADD_PROPERTY (PropertyInfo (Variant::PACKED_BYTE_ARRAY, " data" , PROPERTY_HINT_NONE, " " , PROPERTY_USAGE_NO_EDITOR), " set_data" , " get_data" );
642- ADD_PROPERTY (PropertyInfo (Variant::INT, " format" , PROPERTY_HINT_ENUM, " 8-Bit,16-Bit,IMA-ADPCM" ), " set_format" , " get_format" );
723+ ADD_PROPERTY (PropertyInfo (Variant::INT, " format" , PROPERTY_HINT_ENUM, " 8-Bit,16-Bit,IMA-ADPCM,QOA " ), " set_format" , " get_format" );
643724 ADD_PROPERTY (PropertyInfo (Variant::INT, " loop_mode" , PROPERTY_HINT_ENUM, " Disabled,Forward,Ping-Pong,Backward" ), " set_loop_mode" , " get_loop_mode" );
644725 ADD_PROPERTY (PropertyInfo (Variant::INT, " loop_begin" ), " set_loop_begin" , " get_loop_begin" );
645726 ADD_PROPERTY (PropertyInfo (Variant::INT, " loop_end" ), " set_loop_end" , " get_loop_end" );
@@ -649,6 +730,7 @@ void AudioStreamWAV::_bind_methods() {
649730 BIND_ENUM_CONSTANT (FORMAT_8_BITS);
650731 BIND_ENUM_CONSTANT (FORMAT_16_BITS);
651732 BIND_ENUM_CONSTANT (FORMAT_IMA_ADPCM);
733+ BIND_ENUM_CONSTANT (FORMAT_QOA);
652734
653735 BIND_ENUM_CONSTANT (LOOP_DISABLED);
654736 BIND_ENUM_CONSTANT (LOOP_FORWARD);
0 commit comments