-
-
Notifications
You must be signed in to change notification settings - Fork 309
Description
EncodedAudioStream ignores configured sample rates, always uses 44100 Hz
Description
When using EncodedAudioStream
with encoders like Opus that require specific sample
rates, the configured sample rate is ignored and it always defaults to 44100 Hz,
causing encoder failures with message:
[E] CodecOpus.h : 277 - opus_encoder_create: invalid argument for sample_rate: 44100, channels:2
Steps to Reproduce
- Create an
OpusOggEncoder
andEncodedAudioStream
- Configure audio info with non-44100 Hz sample rate (e.g., 24000 Hz):
AudioInfo info(24000, 2, 16); encoded_stream.setAudioInfo(info); encoded_stream.begin(info);
- Opus encoder fails with: opus_encoder_create: invalid argument for sample_rate:
44100...
Expected Behavior
The encoder should receive the configured 24000 Hz sample rate.
Actual Behavior
The encoder always receives 44100 Hz regardless of configuration.
Root Cause Analysis
I found two potential issues:
- EncodedAudioStream::begin() line 362 calls audioInfo() instead of using configured
values:
return enc_out.begin(audioInfo()); // Uses defaults, not configured values because audioInfo returns enc_out.audioInfo which is
// never changed
- Missing setAudioInfo override in EncodedAudioStream - it doesn't propagate audio
info to enc_out:
// EncodedAudioStream should override setAudioInfo() to call:
// enc_out.setAudioInfo(info);
Proposed Solutions
Option A: Fix the begin() method to use configured audio info
bool begin() override {
// is_output_notify = false;
setupReader();
ReformatBaseStream::begin();
return enc_out.begin(ReformatBaseStream::audioInfo());
}
Option B: Add proper setAudioInfo() override to propagate to enc_out
Impact
This affects anyone using:
- Opus encoding (needs 8k, 12k, 16k, 24k, 48k Hz)
- Any non-44100 Hz encoded audio streams
Environment
- Arduino Audio Tools version: tag v1.1.3
- Platform: ESP32
- Codec: OpusOgg (but likely affects others)
What would be the preferred approach to fix this?
Device Description
ESP32-WROVER-E on the Lilygo T-SIM7600X board
Sketch
/**
* @file Test.cpp
* @brief Minimal reproduction of EncodedAudioStream sample rate bug
* @author Uros Filipovic
* @date 2025-09-15
*
* Demonstrates that EncodedAudioStream ignores configured sample rates
* and always uses 44100 Hz, causing Opus encoder to fail.
*/
#include "utilities.h"
#include "Arduino.h"
#include "AudioTools.h"
#include "AudioTools/AudioCodecs/CodecOpusOgg.h"
// Test configuration - using 24kHz which Opus supports
AudioInfo test_config(24000, 2, 16);
// Simple sine wave for test data
SineWaveGenerator<int16_t> sine_wave(16000);
GeneratedSoundStream<int16_t> sound_source(sine_wave);
// Output to Serial for testing
CsvOutput<int16_t> csv_out(Serial);
// Opus encoder and stream
OpusOggEncoder opus_encoder;
EncodedAudioStream encoded_stream(&csv_out, &opus_encoder);
StreamCopy copier(encoded_stream, sound_source);
void setup() {
Serial.begin(115200);
delay(1000);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
Serial.println("=== EncodedAudioStream Sample Rate Bug Test ===");
Serial.printf("Configured sample rate: %d Hz\n", test_config.sample_rate);
// Configure output
csv_out.begin(test_config);
// Configure sine wave generator
sine_wave.begin(test_config, N_C4);
// Configure Opus encoder
opus_encoder.config().application = OPUS_APPLICATION_AUDIO;
// Test 1: setAudioInfo before begin
Serial.println("\nTest 1: setAudioInfo() then begin()");
encoded_stream.setAudioInfo(test_config);
// Test 2: begin with AudioInfo parameter
Serial.println("Test 2: begin(AudioInfo)");
bool success = encoded_stream.begin(test_config);
// Check results
AudioInfo actual_info = encoded_stream.audioInfo();
Serial.printf("Expected: %d Hz\n", test_config.sample_rate);
Serial.printf("Actual: %d Hz\n", actual_info.sample_rate);
if (success) {
Serial.println("Opus encoder started successfully");
} else {
Serial.println("Opus encoder failed to start");
}
if (actual_info.sample_rate != test_config.sample_rate) {
Serial.println("BUG: Sample rate mismatch detected");
} else {
Serial.println("Sample rate preserved correctly");
}
}
void loop() {
// Try to copy some data if encoder is working
AudioInfo current_info = encoded_stream.audioInfo();
if (current_info.sample_rate == test_config.sample_rate) {
copier.copy();
} else {
delay(1000);
Serial.println("Encoder not working due to sample rate bug");
}
}
Other Steps to Reproduce
I cloned the repository with v1.1.3 tag because in the lib folder of the platformio project. The main branch won't compile with error "driver/i2s_pdm.h: No such file or directory".
The output of the test script is:
=== EncodedAudioStream Sample Rate Bug Test ===
Configured sample rate: 24000 Hz
[I] SoundGenerator.h : 167 - SineWaveGenerator::begin(channels=2, sample_rate=24000, frequency=261.63)
[I] SoundGenerator.h : 150 - bool audio_tools::SineWaveGenerator<T>::begin() [with T = short int]
[I] AudioTypes.h : 125 - SoundGenerator: sample_rate: 24000 / channels: 2 / bits_per_sample: 16
[I] Buffers.h : 415 - resize: 4
[I] SoundGenerator.h : 194 - setFrequency: 261.63
[I] SoundGenerator.h : 195 - active: true
Test 1: setAudioInfo() then begin()
[I] AudioTypes.h : 125 - in: sample_rate: 24000 / channels: 2 / bits_per_sample: 16
[I] AudioTypes.h : 125 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
Test 2: begin(AudioInfo)
[I] AudioTypes.h : 125 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] CodecOpusOgg.h : 95 - writeHeader
[E] CodecOpus.h : 277 - opus_encoder_create: invalid argument for sample_rate: 44100, channels:2
Expected: 24000 Hz
Actual: 44100 Hz
Opus encoder failed to start
BUG: Sample rate mismatch detected
Encoder not working due to sample rate bug
Encoder not working due to sample rate bug
Encoder not working due to sample rate bug
Encoder not working due to sample rate bug
Encoder not working due to sample rate bug
...
What is your development environment (incl. core version info)
Platformio with these env versions:
[env]
platform = espressif32@6.11.0
framework = arduino
I have checked existing issues, discussions and online documentation (incl. the Wiki)
- I confirm I have checked existing issues, discussions and online documentation