-
-
Notifications
You must be signed in to change notification settings - Fork 309
FormatConverterStream causing dropouts (under-runs?) during channel conversion #2135
-
I'm using FormatConverterStream to convert URLstreams with different sampling rates and channel counts, so they can eventually be sent to a mixer for further processing. I've observed the following:
- Sampling Rate conversion works great
- Channel conversion (mono to stereo) works fine for a few seconds before the sound breaks up.
I see no changes in the log when the sound starts breaking up, but the pace of the messages slows down to match the gaps in the audio:
[I] StreamCopy.h : 173 - StreamCopy::copy 1024 -> 1024 -> 1024 bytes - in 1 hops
[I] StreamCopy.h : 173 - StreamCopy::copy 376 -> 376 -> 376 bytes - in 1 hops
(also, if I specify a larger buffer size in the StreamCopy constructor, I see no effect in the copy sizes decribed in the logs, but maybe I'm misunderstanding that?)
Test sketch that shows the problem with a mono -> stereo conversion after a few seconds:
#include "AudioTools.h"
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
const char *ssid = ""; // Change this to your WiFi SSID
const char *password = ""; // Change this to your WiFi password
AudioInfo out_info(44100, 2, 16); // destination format for I2S (all streams will be converted to this)
URLStream url;
I2SStream i2s;
VolumeStream vol(i2s);
FormatConverterStream conv(vol);
MultiDecoder multi(url);
MP3DecoderHelix mp3;
EncodedAudioStream dec(&conv, &multi); // Decoding stream
StreamCopy copier(dec, url); // copy url to decoder
void setup(){
Serial.begin(115200);
Serial.println();
Serial.println("******************************************************");
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
// setup i2s
auto config = i2s.defaultConfig(TX_MODE);
config.copyFrom(out_info);
// Custom I2S pins for my Xaio board
config.pin_ws = 9; // (DAC "LRCK")
config.pin_bck = 7; // (DAC "BCK")
config.pin_data = 8; // (DAC "DIN")
i2s.begin(config);
// setup VolumeStream
auto vcfg = vol.defaultConfig();
vcfg.allow_boost = true; // activate amplification using linear control
vol.begin(vcfg);
// setup audio converter
conv.begin(multi.audioInfo(), out_info);
// setup decoder
multi.addDecoder(mp3, "audio/mpeg");
dec.begin();
url.begin("https://locus.creacast.com:9443/kernot_lillypilly.mp3"); // MONO STREAM
}
void loop() {
copier.copy();
}
Beta Was this translation helpful? Give feedback.
All reactions
I can see the issue in the log: when helix reports mono, I2S is switched to mono, but it should stay as stereo.
[I] AudioTypes.h : 124 - MP3DecoderHelix sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] ResampleStream.h : 145 - setStepSize: 1.000000
[I] ResampleStream.h : 129 - -> ResampleStream:
[I] AudioTypes.h : 124 - in: sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] I2SStream.h : 96 - virtual void audio_tools::I2SStream::setAudioInfo(audio_tools::AudioInfo)
[I] AudioTypes.h : 124 - in: sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] AudioTypes.h : 124 - out: sample_rat...
Replies: 4 comments 4 replies
-
Please share the log: double check that i2s gets informormed about the 2 channels.
Did you try just using the ChannelFormatConverterStream instead ?
Beta Was this translation helpful? Give feedback.
All reactions
-
I haven't tried ChannelFormatConverterStream yet (because I also need samplerate conversion for some streams) but here's the full log. (It seems like I2S begins in stereo, switches to mono but then back to stereo (with 1->2 channel conversion). The odd thing is that the conversion works great for a few seconds before the sound falls apart. (I've tried several streams with different sample rates and channel counts. The problem only occurs on mono streams.)
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] AudioTypes.h : 124 - sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] I2SConfigESP32V1.h : 78 - rx/tx mode: TX_MODE
[I] I2SConfigESP32V1.h : 79 - port_no: 0
[I] I2SConfigESP32V1.h : 80 - is_master: Master
[I] I2SConfigESP32V1.h : 81 - sample rate: 44100
[I] I2SConfigESP32V1.h : 82 - bits per sample: 16
[I] I2SConfigESP32V1.h : 83 - number of channels: 2
[I] I2SConfigESP32V1.h : 84 - signal_type: Digital
[I] I2SConfigESP32V1.h : 85 - buffer_count:6
[I] I2SConfigESP32V1.h : 86 - buffer_size:512
[I] I2SConfigESP32V1.h : 87 - auto_clear: true
[I] I2SConfigESP32V1.h : 89 - i2s_format: I2S_STD_FORMAT
[I] I2SConfigESP32V1.h : 101 - pin_bck: 7
[I] I2SConfigESP32V1.h : 104 - pin_ws: 9
[I] I2SConfigESP32V1.h : 107 - pin_data: 8
[I] I2SESP32V1.h : 259 - dma_frame_num: 768
[I] I2SESP32V1.h : 164 - tx: 8, rx: -1
[I] I2SESP32V1.h : 283 - mclk_multiple=256
[I] VolumeStream.h : 199 - setVolume: 1.000000 at 0
[I] VolumeStream.h : 199 - setVolume: 1.000000 at 1
[I] ResampleStream.h : 129 - -> ResampleStream:
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] I2SStream.h : 96 - virtual void audio_tools::I2SStream::setAudioInfo(audio_tools::AudioInfo)
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] AudioStreamsConverter.h : 465 - -> NumberFormatConverterStream:
[I] AudioStreamsConverter.h : 134 - --> ChannelFormatConverterStream
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] I2SStream.h : 96 - virtual void audio_tools::I2SStream::setAudioInfo(audio_tools::AudioInfo)
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] AudioStreamsConverter.h : 177 - --> ChannelFormatConverterStream
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] AudioStreamsConverter.h : 465 - -> NumberFormatConverterStream:
[I] AudioStreamsConverter.h : 179 - begin 2 -> 2 channels
[I] AudioStreamsConverter.h : 24 - begin 2 -> 2 channels
[I] AudioStreamsConverter.h : 502 - begin 16 -> 16 bits
[I] AudioStreamsConverter.h : 515 - no bit conversion: 16 -> 16
[I] ResampleStream.h : 64 - begin step_size: 1.000000
[I] ResampleStream.h : 145 - setStepSize: 1.000000
[I] ResampleStream.h : 145 - setStepSize: 1.000000
[I] ResampleStream.h : 129 - -> ResampleStream:
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] I2SStream.h : 96 - virtual void audio_tools::I2SStream::setAudioInfo(audio_tools::AudioInfo)
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] URLStream.h : 90 - virtual bool audio_tools::URLStream::begin(const char*, const char*, MethodID, const char*, const char*): https://locus.creacast.com:9443/kernot_lillypilly.mp3
[I] Url.h : 59 - Url::parse
[I] Url.h : 97 - url->https://locus.creacast.com:9443/kernot_lillypilly.mp3
[I] Url.h : 98 - host->locus.creacast.com
[I] Url.h : 99 - protocol->https
[I] Url.h : 100 - path->/kernot_lillypilly.mp3
[I] Url.h : 101 - port->9443
[I] URLStream.h : 378 - WiFiClientSecure
[I] HttpRequest.h : 240 - process connecting to host locus.creacast.com port 9443
[I] HttpRequest.h : 367 - is connected true with timeout 60000
[I] HttpRequest.h : 251 - Free heap: 205412
[I] HttpHeader.h : 262 - HttpHeader::write
[I] HttpHeader.h : 417 - -> GET /kernot_lillypilly.mp3 HTTP/1.1
[I] HttpHeader.h : 196 - -> Host: locus.creacast.com
[I] HttpHeader.h : 196 - -> Connection: keep-alive
[I] HttpHeader.h : 196 - -> Accept-Encoding: identity
[I] HttpHeader.h : 196 - -> Accept: */*
[I] HttpHeader.h : 338 - -> <CR LF>
[I] HttpRequest.h : 316 - Request written ... waiting for reply
[I] HttpHeader.h : 230 - Waiting for data...
[I] HttpHeader.h : 239 - Data available: 481
[I] HttpHeader.h : 110 - Content-Type: audio/mpeg
[I] HttpRequest.h : 181 - no CONTENT_LENGTH found in reply
[I] URLStream.h : 98 - contentLength: 0
[I] URLStream.h : 241 - Request written ... waiting for reply
[I] URLStream.h : 105 - ==> http status: 200
[I] URLStream.h : 105 - ==> http status: 200
[I] MultiDecoder.h : 247 - mime from http request: audio/mpeg
[I] MultiDecoder.h : 199 - Using decoder for audio/mpeg (audio/mpeg)
[I] CodecMP3Helix.h : 82 - virtual bool audio_tools::MP3DecoderHelix::begin()
[I] MultiDecoder.h : 208 - Decoder audio/mpeg started
[I] StreamCopy.h : 173 - StreamCopy::copy 1024 -> 1024 -> 1024 bytes - in 1 hops
[I] StreamCopy.h : 173 - StreamCopy::copy 376 -> 376 -> 376 bytes - in 1 hops
[I] StreamCopy.h : 173 - StreamCopy::copy 1024 -> 1024 -> 1024 bytes - in 1 hops
[I] StreamCopy.h : 173 - StreamCopy::copy 376 -> 376 -> 376 bytes - in 1 hops
[I] AudioTypes.h : 124 - MP3DecoderHelix sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] ResampleStream.h : 145 - setStepSize: 1.000000
[I] ResampleStream.h : 129 - -> ResampleStream:
[I] AudioTypes.h : 124 - in: sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] I2SStream.h : 96 - virtual void audio_tools::I2SStream::setAudioInfo(audio_tools::AudioInfo)
[I] AudioTypes.h : 124 - in: sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] I2SStream.h : 105 - restarting i2s
[I] AudioTypes.h : 124 - I2SStream sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] AudioTypes.h : 124 - sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] I2SConfigESP32V1.h : 78 - rx/tx mode: TX_MODE
[I] I2SConfigESP32V1.h : 79 - port_no: 0
[I] I2SConfigESP32V1.h : 80 - is_master: Master
[I] I2SConfigESP32V1.h : 81 - sample rate: 44100
[I] I2SConfigESP32V1.h : 82 - bits per sample: 16
[I] I2SConfigESP32V1.h : 83 - number of channels: 1
[I] I2SConfigESP32V1.h : 84 - signal_type: Digital
[I] I2SConfigESP32V1.h : 85 - buffer_count:6
[I] I2SConfigESP32V1.h : 86 - buffer_size:512
[I] I2SConfigESP32V1.h : 87 - auto_clear: true
[I] I2SConfigESP32V1.h : 89 - i2s_format: I2S_STD_FORMAT
[I] I2SConfigESP32V1.h : 101 - pin_bck: 7
[I] I2SConfigESP32V1.h : 104 - pin_ws: 9
[I] I2SConfigESP32V1.h : 107 - pin_data: 8
[I] I2SESP32V1.h : 259 - dma_frame_num: 1536
[I] I2SESP32V1.h : 164 - tx: 8, rx: -1
[I] I2SESP32V1.h : 283 - mclk_multiple=256
[W] I2SESP32V1.h : 241 - Using channel_format: I2SChannelSelect::Left for mono
[I] AudioStreamsConverter.h : 465 - -> NumberFormatConverterStream:
[I] AudioTypes.h : 124 - in: sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] ResampleStream.h : 145 - setStepSize: 1.000000
[I] ResampleStream.h : 129 - -> ResampleStream:
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] I2SStream.h : 96 - virtual void audio_tools::I2SStream::setAudioInfo(audio_tools::AudioInfo)
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] AudioStreamsConverter.h : 134 - --> ChannelFormatConverterStream
[I] AudioTypes.h : 124 - in: sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] AudioStreamsConverter.h : 465 - -> NumberFormatConverterStream:
[I] AudioTypes.h : 124 - in: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] ResampleStream.h : 145 - setStepSize: 1.000000
[I] ResampleStream.h : 129 - -> ResampleStream:
[I] AudioTypes.h : 124 - in: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] I2SStream.h : 96 - virtual void audio_tools::I2SStream::setAudioInfo(audio_tools::AudioInfo)
[I] AudioTypes.h : 124 - in: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] I2SStream.h : 105 - restarting i2s
[I] AudioTypes.h : 124 - I2SStream sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] AudioTypes.h : 124 - sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] I2SConfigESP32V1.h : 78 - rx/tx mode: TX_MODE
[I] I2SConfigESP32V1.h : 79 - port_no: 0
[I] I2SConfigESP32V1.h : 80 - is_master: Master
[I] I2SConfigESP32V1.h : 81 - sample rate: 44100
[I] I2SConfigESP32V1.h : 82 - bits per sample: 16
[I] I2SConfigESP32V1.h : 83 - number of channels: 2
[I] I2SConfigESP32V1.h : 84 - signal_type: Digital
[I] I2SConfigESP32V1.h : 85 - buffer_count:6
[I] I2SConfigESP32V1.h : 86 - buffer_size:512
[I] I2SConfigESP32V1.h : 87 - auto_clear: true
[I] I2SConfigESP32V1.h : 89 - i2s_format: I2S_STD_FORMAT
[I] I2SConfigESP32V1.h : 101 - pin_bck: 7
[I] I2SConfigESP32V1.h : 104 - pin_ws: 9
[I] I2SConfigESP32V1.h : 107 - pin_data: 8
[I] I2SESP32V1.h : 259 - dma_frame_num: 768
[I] I2SESP32V1.h : 164 - tx: 8, rx: -1
[I] I2SESP32V1.h : 283 - mclk_multiple=256
[I] AudioTypes.h : 124 - in: sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] AudioTypes.h : 124 - in: sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] I2SStream.h : 96 - virtual void audio_tools::I2SStream::setAudioInfo(audio_tools::AudioInfo)
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] StreamCopy.h : 173 - StreamCopy::copy 1024 -> 1024 -> 1024 bytes - in 1 hops
[I] StreamCopy.h : 173 - StreamCopy::copy 376 -> 376 -> 376 bytes - in 1 hops
[I] StreamCopy.h : 173 - StreamCopy::copy 1024 -> 1024 -> 1024 bytes - in 1 hops
Beta Was this translation helpful? Give feedback.
All reactions
-
A hint:
The mono streams are playing at double the sampling rate. It's been hard to tell on my test streams of environmental audio, but here's an old radio show that makes it obvious:
https://archive.org/download/OTRR_This_Is_Your_FBI_Singles/This%20Is%20Your%20FBI%2051年12月28日%20(352)%20The%20Intruder.mp3
Beta Was this translation helpful? Give feedback.
All reactions
-
I'm bumping this after doing some more troubleshooting. If I pass manually-configured AudioInfo objects to the FormatConverterStream.begin()
method then mono-stereo conversion works perfectly, but if I try to use the automatic propagation from the decoder as an inputconv.begin(multi.audioInfo(), out_info);
then it doesn't seem to update, even though multi.audioInfo()
seems to correctly reflect the currently-loaded stream (based on printing it in the loop).
Even if I refresh it in the loop with conv.setAudioInfo(multi.audioInfo());
after a URL loads, the problem persists. (Stereo streams with different sampling rates seem to work fine, converting 48 to 44.1 when needed, with no pitch changes).
How can I use FormatConverterStream to dynamically change channel-counts after .begin()?
Reminder of the symptoms: mono URLstreams play at double speed for a few seconds and then start stuttering (probably since they are emptying 2x faster than filling).
Beta Was this translation helpful? Give feedback.
All reactions
-
I can see the issue in the log: when helix reports mono, I2S is switched to mono, but it should stay as stereo.
[I] AudioTypes.h : 124 - MP3DecoderHelix sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] ResampleStream.h : 145 - setStepSize: 1.000000
[I] ResampleStream.h : 129 - -> ResampleStream:
[I] AudioTypes.h : 124 - in: sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] I2SStream.h : 96 - virtual void audio_tools::I2SStream::setAudioInfo(audio_tools::AudioInfo)
[I] AudioTypes.h : 124 - in: sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] I2SStream.h : 105 - restarting i2s
I committed a correction: double check if this makes a difference and provide the updated log.
ps. Please note that when you call conv.begin(multi.audioInfo(), out_info), multi.audioInfo() is still stereo because the decoding has not started yet.
Beta Was this translation helpful? Give feedback.
All reactions
-
Thanks for the update. I synced the library changes. The problem persists, though. I included the log from the test above, and also tried a few new things to troubleshoot:
-
Added
conv.end()
andconv.begin(multi.audioInfo(), out_info)
after theurl.begin()
- no improvement -
Added
conv.setAudioInfo(multi.audioInfo())
after theurl.begin()
- no improvement -
In setup() I called manually configured AudioInfo objects
conv.begin(mono_info, stereo_info)
. This worked perfectly. I also switched between the AudioInfo objects in the loop usingconv.setAudioInfo()
and it changed correctly. BUT, if the input toconv.begin()
was the multiDecoder then it ignored futuresetAudioInfo()
attempts. Maybe the MultiDecoder is sending the wrong AudioInfo down the chain, overriding future changes to FormatConverterStream settings? (I've been printingmulti.audioInfo().channels
and it doesn't seem to change between mono and stereo urls.) -
Another detail that confuses me: Even without a FormatConverterStream, a mono stream will play from both channels of my stereo i2s sink, like there's an implicit channel expander somewhere?
The log from test code above:
...[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] AudioTypes.h : 124 - sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] I2SConfigESP32V1.h : 78 - rx/tx mode: TX_MODE
[I] I2SConfigESP32V1.h : 79 - port_no: 0
[I] I2SConfigESP32V1.h : 80 - is_master: Master
[I] I2SConfigESP32V1.h : 81 - sample rate: 44100
[I] I2SConfigESP32V1.h : 82 - bits per sample: 16
[I] I2SConfigESP32V1.h : 83 - number of channels: 2
[I] I2SConfigESP32V1.h : 84 - signal_type: Digital
[I] I2SConfigESP32V1.h : 85 - buffer_count:6
[I] I2SConfigESP32V1.h : 86 - buffer_size:512
[I] I2SConfigESP32V1.h : 87 - auto_clear: true
[I] I2SConfigESP32V1.h : 89 - i2s_format: I2S_STD_FORMAT
[I] I2SConfigESP32V1.h : 101 - pin_bck: 7
[I] I2SConfigESP32V1.h : 104 - pin_ws: 9
[I] I2SConfigESP32V1.h : 107 - pin_data: 8
[I] I2SESP32V1.h : 259 - dma_frame_num: 768
[I] I2SESP32V1.h : 164 - tx: 8, rx: -1
[I] I2SESP32V1.h : 283 - mclk_multiple=256
[I] VolumeStream.h : 199 - setVolume: 1.000000 at 0
[I] VolumeStream.h : 199 - setVolume: 1.000000 at 1
[I] VolumeStream.h : 199 - setVolume: 0.040000 at 0
[I] VolumeStream.h : 199 - setVolume: 0.040000 at 1
[I] AudioStreamsConverter.h : 784 - virtual void audio_tools::FormatConverterStream::setAudioInfo(audio_tools::AudioInfo)
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] I2SStream.h : 96 - virtual void audio_tools::I2SStream::setAudioInfo(audio_tools::AudioInfo)
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] AudioStreamsConverter.h : 134 - --> ChannelFormatConverterStream
[I] AudioStreamsConverter.h : 177 - --> ChannelFormatConverterStream
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] AudioStreamsConverter.h : 465 - -> NumberFormatConverterStream:
[I] AudioStreamsConverter.h : 179 - begin 2 -> 2 channels
[I] AudioStreamsConverter.h : 24 - begin 2 -> 2 channels
[I] AudioStreamsConverter.h : 502 - begin 16 -> 16 bits
[I] AudioStreamsConverter.h : 515 - no bit conversion: 16 -> 16
[I] ResampleStream.h : 64 - begin step_size: 1.000000
[I] ResampleStream.h : 145 - setStepSize: 1.000000
[I] ResampleStream.h : 145 - setStepSize: 1.000000
[I] ResampleStream.h : 129 - -> ResampleStream:
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] I2SStream.h : 96 - virtual void audio_tools::I2SStream::setAudioInfo(audio_tools::AudioInfo)
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] URLStream.h : 90 - virtual bool audio_tools::URLStream::begin(const char*, const char*, MethodID, const char*, const char*): https://s2.yesstreaming.net:17161/stream
[I] Url.h : 59 - Url::parse
[I] Url.h : 97 - url->https://s2.yesstreaming.net:17161/stream
[I] Url.h : 98 - host->s2.yesstreaming.net
[I] Url.h : 99 - protocol->https
[I] Url.h : 100 - path->/stream
[I] Url.h : 101 - port->17161
[I] URLStream.h : 378 - WiFiClientSecure
[I] HttpRequest.h : 240 - process connecting to host s2.yesstreaming.net port 17161
[I] HttpRequest.h : 367 - is connected true with timeout 60000
[I] HttpRequest.h : 251 - Free heap: 178304
[I] HttpHeader.h : 262 - HttpHeader::write
[I] HttpHeader.h : 417 - -> GET /stream HTTP/1.1
[I] HttpHeader.h : 196 - -> Host: s2.yesstreaming.net
[I] HttpHeader.h : 196 - -> Connection: keep-alive
[I] HttpHeader.h : 196 - -> Accept-Encoding: identity
[I] HttpHeader.h : 196 - -> Accept: */*
[I] HttpHeader.h : 338 - -> <CR LF>
[I] HttpRequest.h : 316 - Request written ... waiting for reply
[I] HttpHeader.h : 230 - Waiting for data...
[I] HttpHeader.h : 239 - Data available: 500
[I] HttpHeader.h : 110 - Content-Type: audio/mpeg
[I] HttpRequest.h : 181 - no CONTENT_LENGTH found in reply
[I] URLStream.h : 98 - contentLength: 0
[I] URLStream.h : 241 - Request written ... waiting for reply
[I] URLStream.h : 105 - ==> http status: 200
[I] MultiDecoder.h : 247 - mime from http request: audio/mpeg
[I] MultiDecoder.h : 199 - Using decoder for audio/mpeg (audio/mpeg)
[I] CodecMP3Helix.h : 82 - virtual bool audio_tools::MP3DecoderHelix::begin()
[I] MultiDecoder.h : 208 - Decoder audio/mpeg started
[I] StreamCopy.h : 176 - StreamCopy::copy 1024 -> 1024 -> 1024 bytes - in 1 hops
[I] StreamCopy.h : 176 - StreamCopy::copy 1024 -> 1024 -> 1024 bytes - in 1 hops
[I] AudioTypes.h : 124 - MP3DecoderHelix sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] AudioStreamsConverter.h : 784 - virtual void audio_tools::FormatConverterStream::setAudioInfo(audio_tools::AudioInfo)
[I] AudioTypes.h : 124 - in: sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] I2SStream.h : 96 - virtual void audio_tools::I2SStream::setAudioInfo(audio_tools::AudioInfo)
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] AudioStreamsConverter.h : 134 - --> ChannelFormatConverterStream
[I] AudioTypes.h : 124 - in: sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] AudioStreamsConverter.h : 465 - -> NumberFormatConverterStream:
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] ResampleStream.h : 145 - setStepSize: 1.000000
[I] ResampleStream.h : 129 - -> ResampleStream:
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] I2SStream.h : 96 - virtual void audio_tools::I2SStream::setAudioInfo(audio_tools::AudioInfo)
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] AudioTypes.h : 124 - in: sample_rate: 44100 / channels: 1 / bits_per_sample: 16
[I] AudioTypes.h : 124 - out: sample_rate: 44100 / channels: 2 / bits_per_sample: 16
[I] StreamCopy.h : 176 - StreamCopy::copy 1024 -> 1024 -> 1024 bytes - in 3 hops
[I] StreamCopy.h : 176 - StreamCopy::copy 1024 -> 1024 -> 1024 bytes - in 1 hops
[I] StreamCopy.h : 176 - StreamCopy::copy 1024 -> 1024 -> 1024 bytes - in 1 hops
[I] StreamCopy.h : 176 - StreamCopy::copy 1024 -> 1024 -> 1024 bytes - in 1 hops
Here is a test sketch where I'm alternating between mono and stereo URLS every 10 seconds. (I know you use an AudioKit, so I tried to make it easy: Just flip audioKit
to 1 and hopefully everything will work!
#include "AudioTools.h"
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
#include "AudioTools/AudioLibs/AudioBoardStream.h"
#define audioKit 0 // 0 for Zach's Xaio+DAC, 1 for Phil's AudioKit
const char *ssid = ""; // Change this to your WiFi SSID
const char *password = ""; // Change this to your WiFi password
#if (audioKit == 1)
AudioBoardStream i2s(AudioKitEs8388V1);
#else
I2SStream i2s;
#endif
AudioInfo stereo_info(44100, 2, 16); // destination format for I2S (all streams will be converted to this)
AudioInfo mono_info(44100, 1, 16); // specs for typical mono stream
URLStream url;
VolumeStream vol(i2s);
FormatConverterStream conv(vol);
MultiDecoder multi(url);
MP3DecoderHelix mp3;
EncodedAudioStream dec(&conv, &multi); // Decoding stream
StreamCopy copier(dec, url); // copy url to decoder
static bool lastSwitch = 0;
void setup(){
Serial.begin(115200);
Serial.println();
Serial.println("******************************************************");
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Warning);
// setup i2s
auto config = i2s.defaultConfig(TX_MODE);
config.copyFrom(stereo_info);
if (audioKit == 0) {
// Custom I2S pins for my Xaio board
config.pin_ws = 9; // (DAC "LRCK")
config.pin_bck = 7; // (DAC "BCK")
config.pin_data = 8; // (DAC "DIN")
}
i2s.begin(config);
// setup VolumeStream
auto vcfg = vol.defaultConfig();
vcfg.allow_boost = true; // activate amplification using linear control
vol.begin(vcfg);
if (audioKit == 0) {
vol.setVolume(0.03); // For my setup where amp gain is fixed and very loud!
}
// setup audio converter
conv.begin(mono_info, stereo_info);
// setup decoder
multi.addDecoder(mp3, "audio/mpeg");
dec.begin();
Serial.println("Starting MONO Stream (after conv.begin)");
url.begin("https://s2.yesstreaming.net:17161/stream"); // MONO 44k STREAM
}
void loop() {
copier.copy();
static uint32_t lastSerialOutputTime;
static uint32_t lastURLTime;
char debugInfo[128];
if(millis() - lastSerialOutputTime > 1000){
if (lastSwitch == 1) {
Serial.println("(MONO Stream...)");
} else {
Serial.println("(STEREO Stream...)");
}
snprintf(debugInfo, 96,"STREAM Samplerate: %d, Depth: %d, Channels: %d", multi.audioInfo().sample_rate, multi.audioInfo().bits_per_sample, multi.audioInfo().channels );
Serial.println(debugInfo);
snprintf(debugInfo, 96,"OUTPUT Samplerate: %d, Depth: %d, Channels: %d", i2s.audioInfo().sample_rate, i2s.audioInfo().bits_per_sample, i2s.audioInfo().channels );
Serial.println(debugInfo);
Serial.println("");
lastSerialOutputTime = millis();
}
if(millis() - lastURLTime > 10000) {
if (lastSwitch == 0) {
Serial.println("Starting MONO Stream");
url.end();
//conv.end();
url.begin("https://s2.yesstreaming.net:17161/stream"); // MONO 44k STREAM
conv.setAudioInfo(mono_info);
//conv.begin(multi.audioInfo(), stereo_info);
lastSwitch = 1;
} else {
Serial.println("Starting STEREO Stream");
url.end();
//conv.end();
url.begin("http://s1.voscast.com:8652/stream"); // STEREO 44k STREAM
conv.setAudioInfo(stereo_info);
//conv.begin(multi.audioInfo(), stereo_info);
lastSwitch = 0;
}
lastURLTime = millis();
}
}
Beta Was this translation helpful? Give feedback.
All reactions
-
I committed some corrections to the AudioTools
- channel changes via setAudioInfo() are now automatically restarting the ChannelFormatConverterStream
and LibHelix library
- audio change notifications are sent not only for sample rate but also for channel changes
The following sketch is working now for me. I printing the AudioInfo for the full chain. Please note that it takes at least a copy() step for the decoder to inform about a change:
#include "AudioTools.h" #include "AudioTools/AudioCodecs/CodecMP3Helix.h" #include "AudioTools/AudioLibs/AudioBoardStream.h" #define audioKit 1 // 0 for Zach's Xaio+DAC, 1 for Phil's AudioKit const char *ssid = "tbd"; // Change this to your WiFi SSID const char *password = "tbd"; // Change this to your WiFi password #if (audioKit == 1) AudioBoardStream i2s(AudioKitEs8388V1); #else I2SStream i2s; #endif AudioInfo stereo_info(44100, 2, 16); // destination format for I2S (all streams will be converted to this) AudioInfo mono_info(44100, 1, 16); // specs for typical mono stream URLStream url; VolumeStream vol(i2s); FormatConverterStream conv(vol); MultiDecoder multi(url); MP3DecoderHelix mp3; EncodedAudioStream dec(&conv, &multi); // Decoding stream StreamCopy copier(dec, url); // copy url to decoder static bool lastSwitch = 0; void setup() { Serial.begin(115200); Serial.println(); Serial.println("******************************************************"); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } //AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info); // setup i2s auto config = i2s.defaultConfig(TX_MODE); config.copyFrom(stereo_info); if (audioKit == 0) { // Custom I2S pins for my Xaio board config.pin_ws = 9; // (DAC "LRCK") config.pin_bck = 7; // (DAC "BCK") config.pin_data = 8; // (DAC "DIN") } i2s.begin(config); // setup VolumeStream auto vcfg = vol.defaultConfig(); vcfg.allow_boost = true; // activate amplification using linear control vol.begin(vcfg); if (audioKit == 0) { vol.setVolume(0.03); // For my setup where amp gain is fixed and very loud! } // setup audio converter: any of these variants will work //conv.begin(mono_info, stereo_info); //conv.begin(stereo_info, stereo_info); conv.begin(stereo_info); // setup decoder multi.addDecoder(mp3, "audio/mpeg"); dec.begin(); Serial.println("Starting MONO Stream (after conv.begin)"); url.begin("https://s2.yesstreaming.net:17161/stream"); // MONO 44k STREAM } void loop() { copier.copy(); static uint32_t lastSerialOutputTime; static uint32_t lastURLTime; char debugInfo[128]; if (millis() - lastSerialOutputTime > 1000) { if (lastSwitch == 1) { Serial.println("(MONO Stream...)"); } else { Serial.println("(STEREO Stream...)"); } snprintf(debugInfo, 96, "MP3DecoderHelix Samplerate: %d, Depth: %d, Channels: %d", mp3.audioInfo().sample_rate, mp3.audioInfo().bits_per_sample, mp3.audioInfo().channels); Serial.println(debugInfo); snprintf(debugInfo, 96, "MultiDecoder Samplerate: %d, Depth: %d, Channels: %d", multi.audioInfo().sample_rate, multi.audioInfo().bits_per_sample, multi.audioInfo().channels); Serial.println(debugInfo); snprintf(debugInfo, 96, "EncodedAudioStream Samplerate: %d, Depth: %d, Channels: %d", dec.audioInfo().sample_rate, dec.audioInfo().bits_per_sample, dec.audioInfo().channels); Serial.println(debugInfo); snprintf(debugInfo, 96, "FormatConverterStream In Samplerate: %d, Depth: %d, Channels: %d", conv.audioInfo().sample_rate, conv.audioInfo().bits_per_sample, conv.audioInfo().channels); Serial.println(debugInfo); snprintf(debugInfo, 96, "FormatConverterStream Out Samplerate: %d, Depth: %d, Channels: %d", conv.audioInfoOut().sample_rate, conv.audioInfoOut().bits_per_sample, conv.audioInfoOut().channels); Serial.println(debugInfo); snprintf(debugInfo, 96, "I2SStream Samplerate: %d, Depth: %d, Channels: %d", i2s.audioInfo().sample_rate, i2s.audioInfo().bits_per_sample, i2s.audioInfo().channels); Serial.println(debugInfo); Serial.println(""); lastSerialOutputTime = millis(); } if (millis() - lastURLTime > 10000) { if (lastSwitch == 0) { Serial.println("Starting MONO Stream"); url.end(); url.begin("https://s2.yesstreaming.net:17161/stream"); // MONO 44k STREAM lastSwitch = 1; } else { Serial.println("Starting STEREO Stream"); url.end(); url.begin("http://s1.voscast.com:8652/stream"); // STEREO 44k STREAM lastSwitch = 0; } lastURLTime = millis(); } }
Please also note that the source AudioInfo of the conv.begin(); call does not matter because that will be dynamically refresheshd from the decoder. Only the target matters, so any of this will work:
- conv.begin(mono_info, stereo_info);
- conv.begin(stereo_info, stereo_info);
- conv.begin(stereo_info); // same as conv.begin(stereo_info, stereo_info);
17:10:39.695 -> (STEREO Stream...)
17:10:39.695 -> MP3DecoderHelix Samplerate: 44100, Depth: 16, Channels: 2
17:10:39.695 -> MultiDecoder Samplerate: 44100, Depth: 16, Channels: 2
17:10:39.695 -> EncodedAudioStream Samplerate: 44100, Depth: 16, Channels: 2
17:10:39.695 -> FormatConverterStream In Samplerate: 44100, Depth: 16, Channels: 2
17:10:39.695 -> FormatConverterStream Out Samplerate: 44100, Depth: 16, Channels: 2
17:10:39.695 -> I2SStream Samplerate: 44100, Depth: 16, Channels: 2
...
17:10:44.542 -> (MONO Stream...)
17:10:44.542 -> MP3DecoderHelix Samplerate: 44100, Depth: 16, Channels: 1
17:10:44.542 -> MultiDecoder Samplerate: 44100, Depth: 16, Channels: 1
17:10:44.574 -> EncodedAudioStream Samplerate: 44100, Depth: 16, Channels: 1
17:10:44.574 -> FormatConverterStream In Samplerate: 44100, Depth: 16, Channels: 1
17:10:44.574 -> FormatConverterStream Out Samplerate: 44100, Depth: 16, Channels: 2
17:10:44.574 -> I2SStream Samplerate: 44100, Depth: 16, Channels: 2
Beta Was this translation helpful? Give feedback.
All reactions
-
I'm getting close to a deadline on a project and this update is like a ray of sunshine in the clouds. Thank you so much... for the libraries, for your willingness to track down bugs, and for your valuable explanations and examples.
Beta Was this translation helpful? Give feedback.