Skip to content

Commit

Permalink
Correct ADPCM
Browse files Browse the repository at this point in the history
  • Loading branch information
pschatzmann committed Sep 25, 2024
1 parent 2d3fc49 commit 2e88628
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 16 deletions.
8 changes: 5 additions & 3 deletions examples/tests/codecs/test-codec-adpcm/test-codec-adpcm.ino
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ SineWaveGenerator<int16_t> sineWave( 32000); // subclass of SoundGenerator with
GeneratedSoundStream<int16_t> sound( sineWave); // Stream generated from sine wave
//AudioBoardStream out(AudioKitEs8388V1);
//I2SStream out;
AudioBoardStream out(AudioKitEs8388V1);
EncodedAudioStream decoder(&out, new ADPCMDecoder(AV_CODEC_ID_ADPCM_IMA_WAV)); // encode and write
EncodedAudioStream encoder(&decoder, new ADPCMEncoder(AV_CODEC_ID_ADPCM_IMA_WAV)); // encode and write
//AudioBoardStream out(AudioKitEs8388V1);
CsvOutput<int16_t> out(Serial);
AVCodecID id = AV_CODEC_ID_ADPCM_IMA_WAV;
EncodedAudioStream decoder(&out, new ADPCMDecoder(id)); // encode and write
EncodedAudioStream encoder(&decoder, new ADPCMEncoder(id)); // encode and write
StreamCopy copier(encoder, sound);

void setup() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include "AudioTools.h"
#include "AudioCodecs/CodecWAV.h"
#include "AudioCodecs/CodecADPCM.h"

AudioInfo info(16000, 2, 16);
SineWaveGenerator<int16_t> sineWave( 32000);
GeneratedSoundStream<int16_t> sound( sineWave);
CsvOutput<int16_t> out(Serial);
AVCodecID id = AV_CODEC_ID_ADPCM_IMA_WAV;
ADPCMDecoder adpcm_decoder(id);
ADPCMEncoder adpcm_encoder(id);
WAVDecoder wav_decoder(adpcm_decoder, AudioFormat::ADPCM);
WAVEncoder wav_encoder(adpcm_encoder, AudioFormat::ADPCM);
EncodedAudioStream decoder(&out, &wav_decoder);
EncodedAudioStream encoder(&decoder, &wav_encoder);
StreamCopy copier(encoder, sound);

void setup() {
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Warning);

// start Output
auto cfgi = out.defaultConfig(TX_MODE);
cfgi.copyFrom(info);
out.begin(cfgi);

// Setup sine wave
auto cfgs = sineWave.defaultConfig();
cfgs.copyFrom(info);
sineWave.begin(info, N_B4);

// start decoder
decoder.begin(info);

// start encoder
encoder.begin(info);
}

void loop() {
copier.copy();
}
25 changes: 15 additions & 10 deletions src/AudioCodecs/CodecWAV.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,13 +149,14 @@ class WAVHeader {
}

/// Just write a wav header to the indicated output
void writeHeader(Print *out) {
int writeHeader(Print *out) {
SingleBuffer<uint8_t> buffer(50);
writeRiffHeader(buffer);
writeFMT(buffer);
writeDataHeader(buffer);
len = buffer.available();
out->write(buffer.data(), buffer.available());
return len;
}

protected:
Expand Down Expand Up @@ -325,9 +326,9 @@ class WAVDecoder : public AudioDecoder {
if (active) {
if (isFirst) {
result = decodeHeader((uint8_t*) data, len);
if (result<len){
result += write_out((uint8_t *)data+result, len-result);
}
// if (result<len){
// result += write_out((uint8_t *)data+result, len-result);
// }
} else if (isValid) {
result = write_out((uint8_t *)data, len);
}
Expand All @@ -354,7 +355,8 @@ class WAVDecoder : public AudioDecoder {
virtual size_t write_out(const uint8_t *in_ptr, size_t in_size) {
// check if we need to convert int24 data from 3 bytes to 4 bytes
size_t result = 0;
if (header.audioInfo().bits_per_sample == 24 && sizeof(int24_t)==4){
if (header.audioInfo().format == AudioFormat::PCM
&& header.audioInfo().bits_per_sample == 24 && sizeof(int24_t)==4){
write_out_24(in_ptr, in_size);
result = in_size;
} else {
Expand Down Expand Up @@ -440,8 +442,10 @@ class WAVDecoder : public AudioDecoder {
bi.bits_per_sample = header.audioInfo().bits_per_sample;
notifyAudioChange(bi);
// write prm data from first record
LOGI("WAVDecoder writing first sound data");
result = out().write(sound_ptr, len);
if (len > 0) {
LOGI("WAVDecoder writing first sound data");
result = out().write(sound_ptr, len);
}
} else {
LOGE("WAV format not supported: %d", (int)format);
}
Expand All @@ -453,7 +457,7 @@ class WAVDecoder : public AudioDecoder {
assert(p_print!=nullptr);
dec_out.setOutput(p_print);
dec_out.setDecoder(p_decoder);
dec_out.begin();
dec_out.begin(info);
}
}
};
Expand Down Expand Up @@ -522,6 +526,7 @@ class WAVEncoder : public AudioEncoder {
/// Defines the WAVAudioInfo
virtual void setAudioInfo(WAVAudioInfo ai) {
AudioEncoder::setAudioInfo(ai);
if (p_encoder) p_encoder->setAudioInfo(ai);
audioInfo = ai;
LOGI("sample_rate: %d", (int)audioInfo.sample_rate);
LOGI("channels: %d", audioInfo.channels);
Expand Down Expand Up @@ -575,8 +580,8 @@ class WAVEncoder : public AudioEncoder {
if (!header_written) {
LOGI("Writing Header");
header.setAudioInfo(audioInfo);
header.writeHeader(p_print);
audioInfo.file_size -= 44;
int len = header.writeHeader(p_print);
audioInfo.file_size -= len;
header_written = true;
}

Expand Down
4 changes: 4 additions & 0 deletions src/AudioTools/AudioOutput.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,10 @@ template <typename T> class CsvOutput : public AudioOutput {
return 0;
}

if (len==0){
return 0;
}

if (cfg.channels == 0) {
LOGW("Channels not defined: using 2");
cfg.channels = 2;
Expand Down
6 changes: 3 additions & 3 deletions tests-cmake/codec/wav/wav.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ AudioInfo info(16000, 2, 16);
SineWaveGenerator<int16_t> sineWave( 32000); // subclass of SoundGenerator with max amplitude of 32000
GeneratedSoundStream<int16_t> sound( sineWave); // Stream generated from sine wave
//I2SStream out;
PortAudioStream out;
//CsvOutput<int16_t> out(Serial);
//PortAudioStream out;
CsvOutput<int16_t> out(Serial);
#if USE_ADPCM
ADPCMDecoder adpcm_decoder(AV_CODEC_ID_ADPCM_IMA_WAV);
ADPCMEncoder adpcm_encoder(AV_CODEC_ID_ADPCM_IMA_WAV);
Expand All @@ -35,7 +35,7 @@ StreamCopy copier(encoder, sound);

void setup() {
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Warning);
AudioLogger::instance().begin(Serial, AudioLogger::Debug);

// start I2S
Serial.println("starting Output...");
Expand Down

0 comments on commit 2e88628

Please sign in to comment.