Skip to content

Commit ebb018c

Browse files
committed
NPE in SPDIFStream
1 parent ad06a5d commit ebb018c

File tree

1 file changed

+58
-51
lines changed

1 file changed

+58
-51
lines changed

src/AudioExperiments/AudioSPDIF.h

Lines changed: 58 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -114,14 +114,15 @@ struct SPDIFConfig : public AudioBaseInfo {
114114
SPDIFConfig() {
115115
bits_per_sample = 16;
116116
channels = 2;
117+
sample_rate = 44100;
117118
}
118119
int port_no = 0; // processor dependent port
119120
int pin_data = SPDIF_DATA_PIN;
120121
};
121122

122123
/**
123124
* @brief Interface definition for SPDIF output class
124-
*
125+
*
125126
*/
126127
class SPDIFOut {
127128
public:
@@ -131,8 +132,8 @@ class SPDIFOut {
131132
};
132133

133134
/**
134-
* @brief Generic I2S Output
135-
*
135+
* @brief Generic I2S Output
136+
*
136137
*/
137138
class SPDIFOutI2S : public SPDIFOut {
138139
public:
@@ -172,47 +173,49 @@ class SPDIFOutI2S : public SPDIFOut {
172173

173174
#ifdef ESP32
174175
/**
175-
* @brief ESP32 specific Output
176-
*
176+
* @brief ESP32 specific Output
177+
*
177178
*/
178179
class SPDFOutI2SESP32 : public SPDIFOut {
179180
public:
180181
SPDFOutI2SESP32() = default;
181182

182183
// initialize I2S for S/PDIF transmission
183184
void begin(SPDIFConfig &cfg) {
184-
// uninstall and reinstall I2S driver for avoiding I2S bug
185-
int sample_rate = cfg.sample_rate * BMC_BITS_FACTOR;
186-
int bclk = sample_rate * I2S_BITS_PER_SAMPLE * I2S_CHANNELS;
187-
int mclk = (I2S_BUG_MAGIC / bclk) * bclk; // use mclk for avoiding I2S bug
188-
189-
i2s_config_t i2s_config = {
190-
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
191-
.sample_rate = sample_rate,
192-
.bits_per_sample = (i2s_bits_per_sample_t)I2S_BITS_PER_SAMPLE,
193-
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
194-
.communication_format = (i2s_comm_format_t)I2S_COMM_FORMAT_STAND_I2S,
195-
.intr_alloc_flags = 0,
196-
.dma_buf_count = DMA_BUF_COUNT,
197-
.dma_buf_len = DMA_BUF_LEN,
198-
.use_apll = true,
199-
.tx_desc_auto_clear = true,
200-
.fixed_mclk = mclk, // avoiding I2S bug
201-
};
202-
i2s_pin_config_t pin_config = {
203-
.bck_io_num = -1,
204-
.ws_io_num = -1,
205-
.data_out_num = cfg.pin_data,
206-
.data_in_num = -1,
207-
};
208-
209-
ESP_ERROR_CHECK(i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL));
210-
ESP_ERROR_CHECK(i2s_set_pin(I2S_NUM, &pin_config));
185+
if (cfg.sample_rate != 0) {
186+
// uninstall and reinstall I2S driver for avoiding I2S bug
187+
int sample_rate = cfg.sample_rate * BMC_BITS_FACTOR;
188+
int bclk = sample_rate * I2S_BITS_PER_SAMPLE * I2S_CHANNELS;
189+
int mclk =
190+
(I2S_BUG_MAGIC / bclk) * bclk; // use mclk for avoiding I2S bug
191+
192+
i2s_config_t i2s_config = {
193+
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
194+
.sample_rate = sample_rate,
195+
.bits_per_sample = (i2s_bits_per_sample_t)I2S_BITS_PER_SAMPLE,
196+
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
197+
.communication_format = (i2s_comm_format_t)I2S_COMM_FORMAT_STAND_I2S,
198+
.intr_alloc_flags = 0,
199+
.dma_buf_count = DMA_BUF_COUNT,
200+
.dma_buf_len = DMA_BUF_LEN,
201+
.use_apll = true,
202+
.tx_desc_auto_clear = true,
203+
.fixed_mclk = mclk, // avoiding I2S bug
204+
};
205+
i2s_pin_config_t pin_config = {
206+
.bck_io_num = -1,
207+
.ws_io_num = -1,
208+
.data_out_num = cfg.pin_data,
209+
.data_in_num = -1,
210+
};
211+
ESP_ERROR_CHECK(i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL));
212+
ESP_ERROR_CHECK(i2s_set_pin(I2S_NUM, &pin_config));
213+
} else {
214+
LOGE("sample_rate must not be null")
215+
}
211216
}
212217

213-
bool end() {
214-
return i2s_driver_uninstall(I2S_NUM) == ESP_OK;
215-
}
218+
bool end() { return i2s_driver_uninstall(I2S_NUM) == ESP_OK; }
216219

217220
size_t write(uint8_t *spdif_buf, size_t len) {
218221
size_t i2s_write_len;
@@ -230,8 +233,8 @@ class SPDFOutI2SESP32 : public SPDIFOut {
230233
class SPDIFOutGeneric : public SPDIFOut {
231234
public:
232235
SPDIFOutGeneric(Print &out) { this->out = &out; }
233-
virtual void begin(SPDIFConfig &cfg) { }
234-
virtual bool end() {return true;}
236+
virtual void begin(SPDIFConfig &cfg) {}
237+
virtual bool end() { return true; }
235238

236239
virtual size_t write(uint8_t *data, size_t len) {
237240
return out->write(data, len);
@@ -253,24 +256,28 @@ class SPDIFStream16Bit2Channels : public AudioStreamX {
253256
SPDIFStream16Bit2Channels() = default;
254257

255258
/// destructor
256-
~SPDIFStream16Bit2Channels() { end(); }
259+
virtual ~SPDIFStream16Bit2Channels() { end(); }
257260

258261
/// Starting with default settings
259262
bool begin() { return begin(defaultConfig()); }
260263

261264
/// Start with the provided parameters
262265
bool begin(SPDIFConfig cfg) {
263-
if (i2sOn){
266+
if (i2sOn) {
264267
out->end();
265268
}
266269

267270
// initialize S/PDIF buffer
268271
spdif_buf_init();
269272
spdif_ptr = spdif_buf;
270-
out->begin(cfg);
273+
if (out != nullptr) {
274+
out->begin(cfg);
275+
i2sOn = true;
276+
} else {
277+
LOGE("out is null - please call setOutput() ");
278+
}
271279

272-
i2sOn = true;
273-
return true;
280+
return i2sOn;
274281
}
275282

276283
bool end() {
@@ -286,7 +293,7 @@ class SPDIFStream16Bit2Channels : public AudioStreamX {
286293
void setOutput(SPDIFOut *out_ptr) { this->out = out_ptr; }
287294

288295
/// Change the audio parameters
289-
virtual void setAudioInfo(AudioBaseInfo info) {
296+
void setAudioInfo(AudioBaseInfo info) {
290297
cfg.bits_per_sample = info.bits_per_sample;
291298
cfg.channels = info.channels;
292299
cfg.sample_rate = info.sample_rate;
@@ -308,6 +315,7 @@ class SPDIFStream16Bit2Channels : public AudioStreamX {
308315

309316
/// Writes the audio data as SPDIF to the defined output pin
310317
size_t write(const uint8_t *src, size_t size) {
318+
if (out == nullptr) return 0;
311319
const uint8_t *p = src;
312320
size_t result = 0;
313321

@@ -361,19 +369,19 @@ class SPDIFStream : public AudioStreamX {
361369
SPDIFStream() = default;
362370

363371
/// Constructor which is defining a specific output class
364-
SPDIFStream(Print &out){
372+
SPDIFStream(Print &out) {
365373
spdif_out = new SPDIFOutGeneric(out);
366374
spdif.setOutput(spdif_out);
367375
}
368376

369-
///Destructor
370-
~SPDIFStream() {
377+
/// Destructor
378+
virtual ~SPDIFStream() {
371379
end();
372-
if (spdif_out!=nullptr){
380+
if (spdif_out != nullptr) {
373381
delete spdif_out;
374382
spdif_out = nullptr;
375383
}
376-
}
384+
}
377385

378386
/// start SPDIF with default configuration
379387
bool begin() { return spdif.begin(); }
@@ -404,14 +412,13 @@ class SPDIFStream : public AudioStreamX {
404412
targetSpdifConfig.bits_per_sample = 16;
405413
targetSpdifConfig.sample_rate = cfg.sample_rate;
406414
return spdif.begin(targetSpdifConfig);
407-
408415
}
409416

410417
/// Close the SPDIF processing
411418
bool end() { return spdif.end(); }
412419

413420
/// Provide audio data to SPDIF
414-
size_t write(const uint8_t *src, size_t size) {
421+
size_t write(const uint8_t *src, size_t size) override {
415422
return converter.write(src, size);
416423
}
417424

@@ -431,7 +438,7 @@ class SPDIFStream : public AudioStreamX {
431438
SPDIFConfig cfg;
432439
SPDIFStream16Bit2Channels spdif;
433440
FormatConverterStream converter{spdif};
434-
SPDIFOut *spdif_out=nullptr;
441+
SPDIFOut *spdif_out = nullptr;
435442
};
436443

437444
} // namespace audio_tools

0 commit comments

Comments
 (0)