@@ -114,14 +114,15 @@ struct SPDIFConfig : public AudioBaseInfo {
114
114
SPDIFConfig () {
115
115
bits_per_sample = 16 ;
116
116
channels = 2 ;
117
+ sample_rate = 44100 ;
117
118
}
118
119
int port_no = 0 ; // processor dependent port
119
120
int pin_data = SPDIF_DATA_PIN;
120
121
};
121
122
122
123
/* *
123
124
* @brief Interface definition for SPDIF output class
124
- *
125
+ *
125
126
*/
126
127
class SPDIFOut {
127
128
public:
@@ -131,8 +132,8 @@ class SPDIFOut {
131
132
};
132
133
133
134
/* *
134
- * @brief Generic I2S Output
135
- *
135
+ * @brief Generic I2S Output
136
+ *
136
137
*/
137
138
class SPDIFOutI2S : public SPDIFOut {
138
139
public:
@@ -172,47 +173,49 @@ class SPDIFOutI2S : public SPDIFOut {
172
173
173
174
#ifdef ESP32
174
175
/* *
175
- * @brief ESP32 specific Output
176
- *
176
+ * @brief ESP32 specific Output
177
+ *
177
178
*/
178
179
class SPDFOutI2SESP32 : public SPDIFOut {
179
180
public:
180
181
SPDFOutI2SESP32 () = default ;
181
182
182
183
// initialize I2S for S/PDIF transmission
183
184
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
+ }
211
216
}
212
217
213
- bool end () {
214
- return i2s_driver_uninstall (I2S_NUM) == ESP_OK;
215
- }
218
+ bool end () { return i2s_driver_uninstall (I2S_NUM) == ESP_OK; }
216
219
217
220
size_t write (uint8_t *spdif_buf, size_t len) {
218
221
size_t i2s_write_len;
@@ -230,8 +233,8 @@ class SPDFOutI2SESP32 : public SPDIFOut {
230
233
class SPDIFOutGeneric : public SPDIFOut {
231
234
public:
232
235
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 ; }
235
238
236
239
virtual size_t write (uint8_t *data, size_t len) {
237
240
return out->write (data, len);
@@ -253,24 +256,28 @@ class SPDIFStream16Bit2Channels : public AudioStreamX {
253
256
SPDIFStream16Bit2Channels () = default ;
254
257
255
258
// / destructor
256
- ~SPDIFStream16Bit2Channels () { end (); }
259
+ virtual ~SPDIFStream16Bit2Channels () { end (); }
257
260
258
261
// / Starting with default settings
259
262
bool begin () { return begin (defaultConfig ()); }
260
263
261
264
// / Start with the provided parameters
262
265
bool begin (SPDIFConfig cfg) {
263
- if (i2sOn){
266
+ if (i2sOn) {
264
267
out->end ();
265
268
}
266
269
267
270
// initialize S/PDIF buffer
268
271
spdif_buf_init ();
269
272
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
+ }
271
279
272
- i2sOn = true ;
273
- return true ;
280
+ return i2sOn;
274
281
}
275
282
276
283
bool end () {
@@ -286,7 +293,7 @@ class SPDIFStream16Bit2Channels : public AudioStreamX {
286
293
void setOutput (SPDIFOut *out_ptr) { this ->out = out_ptr; }
287
294
288
295
// / Change the audio parameters
289
- virtual void setAudioInfo (AudioBaseInfo info) {
296
+ void setAudioInfo (AudioBaseInfo info) {
290
297
cfg.bits_per_sample = info.bits_per_sample ;
291
298
cfg.channels = info.channels ;
292
299
cfg.sample_rate = info.sample_rate ;
@@ -308,6 +315,7 @@ class SPDIFStream16Bit2Channels : public AudioStreamX {
308
315
309
316
// / Writes the audio data as SPDIF to the defined output pin
310
317
size_t write (const uint8_t *src, size_t size) {
318
+ if (out == nullptr ) return 0 ;
311
319
const uint8_t *p = src;
312
320
size_t result = 0 ;
313
321
@@ -361,19 +369,19 @@ class SPDIFStream : public AudioStreamX {
361
369
SPDIFStream () = default ;
362
370
363
371
// / Constructor which is defining a specific output class
364
- SPDIFStream (Print &out){
372
+ SPDIFStream (Print &out) {
365
373
spdif_out = new SPDIFOutGeneric (out);
366
374
spdif.setOutput (spdif_out);
367
375
}
368
376
369
- // /Destructor
370
- ~SPDIFStream () {
377
+ // / Destructor
378
+ virtual ~SPDIFStream () {
371
379
end ();
372
- if (spdif_out!= nullptr ){
380
+ if (spdif_out != nullptr ) {
373
381
delete spdif_out;
374
382
spdif_out = nullptr ;
375
383
}
376
- }
384
+ }
377
385
378
386
// / start SPDIF with default configuration
379
387
bool begin () { return spdif.begin (); }
@@ -404,14 +412,13 @@ class SPDIFStream : public AudioStreamX {
404
412
targetSpdifConfig.bits_per_sample = 16 ;
405
413
targetSpdifConfig.sample_rate = cfg.sample_rate ;
406
414
return spdif.begin (targetSpdifConfig);
407
-
408
415
}
409
416
410
417
// / Close the SPDIF processing
411
418
bool end () { return spdif.end (); }
412
419
413
420
// / 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 {
415
422
return converter.write (src, size);
416
423
}
417
424
@@ -431,7 +438,7 @@ class SPDIFStream : public AudioStreamX {
431
438
SPDIFConfig cfg;
432
439
SPDIFStream16Bit2Channels spdif;
433
440
FormatConverterStream converter{spdif};
434
- SPDIFOut *spdif_out= nullptr ;
441
+ SPDIFOut *spdif_out = nullptr ;
435
442
};
436
443
437
444
} // namespace audio_tools
0 commit comments