@@ -111,14 +111,132 @@ static uint32_t *spdif_ptr;
111
111
* @copyright GPLv3
112
112
*/
113
113
struct SPDIFConfig : public AudioBaseInfo {
114
- SPDIFConfig (){
114
+ SPDIFConfig () {
115
115
bits_per_sample = 16 ;
116
116
channels = 2 ;
117
117
}
118
118
int port_no = 0 ; // processor dependent port
119
119
int pin_data = SPDIF_DATA_PIN;
120
120
};
121
121
122
+ /* *
123
+ * @brief Interface definition for SPDIF output class
124
+ *
125
+ */
126
+ class SPDIFOut {
127
+ public:
128
+ virtual void begin (SPDIFConfig &cfg);
129
+ virtual bool end ();
130
+ virtual size_t write (uint8_t *spdif_buf, size_t len);
131
+ };
132
+
133
+ /* *
134
+ * @brief Generic I2S Output
135
+ *
136
+ */
137
+ class SPDIFOutI2S : public SPDIFOut {
138
+ public:
139
+ SPDIFOutI2S () = default ;
140
+
141
+ void begin (SPDIFConfig &cfg) {
142
+ int sample_rate = cfg.sample_rate * BMC_BITS_FACTOR;
143
+ int bclk = sample_rate * I2S_BITS_PER_SAMPLE * I2S_CHANNELS;
144
+ int mclk = (I2S_BUG_MAGIC / bclk) * bclk; // use mclk for avoiding I2S bug
145
+
146
+ I2SConfig i2s_cfg;
147
+ i2s_cfg.sample_rate = sample_rate;
148
+ i2s_cfg.channels = cfg.channels ;
149
+ i2s_cfg.bits_per_sample = 32 ;
150
+ i2s_cfg.pin_ws = -1 ;
151
+ i2s_cfg.pin_bck = -1 ;
152
+ i2s_cfg.pin_data = cfg.pin_data ;
153
+ i2s_cfg.use_apll = true ;
154
+ i2s_cfg.fixed_mclk = mclk;
155
+
156
+ i2s.begin (i2s_cfg);
157
+ }
158
+
159
+ bool end () {
160
+ i2s.end ();
161
+ return true ;
162
+ }
163
+
164
+ size_t write (uint8_t *spdif_buf, size_t len) {
165
+ return i2s.write (spdif_buf, len);
166
+ }
167
+
168
+ protected:
169
+ I2SStream i2s;
170
+ };
171
+
172
+ /* *
173
+ * @brief ESP32 specific Output
174
+ *
175
+ */
176
+ class SPDFOutI2SESP32 : public SPDIFOut {
177
+ public:
178
+ SPDFOutI2SESP32 () = default ;
179
+
180
+ // initialize I2S for S/PDIF transmission
181
+ void begin (SPDIFConfig &cfg) {
182
+ // uninstall and reinstall I2S driver for avoiding I2S bug
183
+ int sample_rate = cfg.sample_rate * BMC_BITS_FACTOR;
184
+ int bclk = sample_rate * I2S_BITS_PER_SAMPLE * I2S_CHANNELS;
185
+ int mclk = (I2S_BUG_MAGIC / bclk) * bclk; // use mclk for avoiding I2S bug
186
+
187
+ i2s_config_t i2s_config = {
188
+ .mode = (i2s_mode_t )(I2S_MODE_MASTER | I2S_MODE_TX),
189
+ .sample_rate = sample_rate,
190
+ .bits_per_sample = (i2s_bits_per_sample_t )I2S_BITS_PER_SAMPLE,
191
+ .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
192
+ .communication_format = (i2s_comm_format_t )I2S_COMM_FORMAT_STAND_I2S,
193
+ .intr_alloc_flags = 0 ,
194
+ .dma_buf_count = DMA_BUF_COUNT,
195
+ .dma_buf_len = DMA_BUF_LEN,
196
+ .use_apll = true ,
197
+ .tx_desc_auto_clear = true ,
198
+ .fixed_mclk = mclk, // avoiding I2S bug
199
+ };
200
+ i2s_pin_config_t pin_config = {
201
+ .bck_io_num = -1 ,
202
+ .ws_io_num = -1 ,
203
+ .data_out_num = cfg.pin_data ,
204
+ .data_in_num = -1 ,
205
+ };
206
+
207
+ ESP_ERROR_CHECK (i2s_driver_install (I2S_NUM, &i2s_config, 0 , NULL ));
208
+ ESP_ERROR_CHECK (i2s_set_pin (I2S_NUM, &pin_config));
209
+ }
210
+
211
+ bool end () {
212
+ return i2s_driver_uninstall (I2S_NUM) == ESP_OK;
213
+ }
214
+
215
+ size_t write (uint8_t *spdif_buf, size_t len) {
216
+ size_t i2s_write_len;
217
+ i2s_write (I2S_NUM, spdif_buf, len, &i2s_write_len, portMAX_DELAY);
218
+ return i2s_write_len;
219
+ }
220
+ };
221
+
222
+ /* *
223
+ * @brief Generic output of SPDIF to Arduino Stream
224
+ *
225
+ */
226
+ class SPDIFOutGeneric : public SPDIFOut {
227
+ public:
228
+ SPDIFOutGeneric (Print &out) { this ->out = &out; }
229
+ virtual void begin (SPDIFConfig &cfg) { }
230
+ virtual bool end () {return true ;}
231
+
232
+ virtual size_t write (uint8_t *data, size_t len) {
233
+ return out->write (data, len);
234
+ }
235
+
236
+ protected:
237
+ Print *out = nullptr ;
238
+ };
239
+
122
240
/* *
123
241
* @brief Output as 16 bit stereo SPDIF on the I2S data output pin
124
242
* @author Phil Schatzmann
@@ -127,22 +245,51 @@ struct SPDIFConfig : public AudioBaseInfo {
127
245
*/
128
246
class SPDIFStream16Bit2Channels : public AudioStreamX {
129
247
public:
248
+ // / default constructor
130
249
SPDIFStream16Bit2Channels () = default ;
131
250
251
+ // / destructor
252
+ ~SPDIFStream16Bit2Channels () { end (); }
253
+
132
254
// / Starting with default settings
133
255
bool begin () { return begin (defaultConfig ()); }
134
256
135
257
// / Start with the provided parameters
136
258
bool begin (SPDIFConfig cfg) {
259
+ if (out == nullptr ) {
260
+ #if USE_ESP32_I2S == 1
261
+ out = new SPDFOutI2SESP32 ();
262
+ #else
263
+ out = new SPDIFOutI2S ();
264
+ #endif
265
+ }
266
+ if (i2sOn){
267
+ out->end ();
268
+ }
269
+
137
270
// initialize S/PDIF buffer
138
271
spdif_buf_init ();
139
272
spdif_ptr = spdif_buf;
273
+ out->begin (cfg);
140
274
141
- spdif_init (cfg);
142
275
i2sOn = true ;
143
276
return true ;
144
277
}
145
278
279
+ bool end () {
280
+ bool result = true ;
281
+ if (out != nullptr ) {
282
+ result = out->end ();
283
+ delete out;
284
+ out = nullptr ;
285
+ }
286
+ i2sOn = false ;
287
+ return result;
288
+ }
289
+
290
+ // / Defines the Output
291
+ void setOutput (SPDIFOut *out_ptr) { this ->out = out_ptr; }
292
+
146
293
// / Change the audio parameters
147
294
virtual void setAudioInfo (AudioBaseInfo info) {
148
295
cfg.bits_per_sample = info.bits_per_sample ;
@@ -153,8 +300,7 @@ class SPDIFStream16Bit2Channels : public AudioStreamX {
153
300
info.bits_per_sample );
154
301
}
155
302
if (info.channels != 2 ) {
156
- LOGE (" Unsupported number of channels: %d - must be 2!" ,
157
- info.channels );
303
+ LOGE (" Unsupported number of channels: %d - must be 2!" , info.channels );
158
304
}
159
305
begin (cfg);
160
306
}
@@ -184,37 +330,18 @@ class SPDIFStream16Bit2Channels : public AudioStreamX {
184
330
// set block start preamble
185
331
((uint8_t *)spdif_buf)[SYNC_OFFSET] ^= SYNC_FLIP;
186
332
187
- result += spdif_write ((uint8_t *)spdif_buf, sizeof (spdif_buf));
333
+ result += out-> write ((uint8_t *)spdif_buf, sizeof (spdif_buf));
188
334
spdif_ptr = spdif_buf;
189
335
}
190
336
}
191
337
192
338
return result / 2 ;
193
339
}
194
340
195
- #if USE_ESP32_I2S == 1
196
-
197
- bool end () {
198
- i2sOn = false ;
199
- return i2s_driver_uninstall (I2S_NUM) == ESP_OK;
200
- }
201
-
202
- #else
203
-
204
- bool end () {
205
- i2s.end ();
206
- i2sOn = false ;
207
- return true ;
208
- }
209
-
210
- #endif
211
-
212
341
protected:
213
- bool i2sOn;
342
+ bool i2sOn = false ;
214
343
SPDIFConfig cfg;
215
- #if USE_ESP32_I2S != 1
216
- I2SStream i2s;
217
- #endif
344
+ SPDIFOut *out = nullptr ;
218
345
219
346
// initialize S/PDIF buffer
220
347
static void spdif_buf_init (void ) {
@@ -225,83 +352,34 @@ class SPDIFStream16Bit2Channels : public AudioStreamX {
225
352
spdif_buf[i] = bmc_mw ^= BMC_MW_DIF;
226
353
}
227
354
}
228
-
229
- #if USE_ESP32_I2S == 1
230
- // initialize I2S for S/PDIF transmission
231
- void spdif_init (SPDIFConfig &cfg) {
232
- // uninstall and reinstall I2S driver for avoiding I2S bug
233
- if (i2sOn) {
234
- end ();
235
- }
236
- int sample_rate = cfg.sample_rate * BMC_BITS_FACTOR;
237
- int bclk = sample_rate * I2S_BITS_PER_SAMPLE * I2S_CHANNELS;
238
- int mclk = (I2S_BUG_MAGIC / bclk) * bclk; // use mclk for avoiding I2S bug
239
-
240
- i2s_config_t i2s_config = {
241
- .mode = (i2s_mode_t )(I2S_MODE_MASTER | I2S_MODE_TX),
242
- .sample_rate = sample_rate,
243
- .bits_per_sample = (i2s_bits_per_sample_t )I2S_BITS_PER_SAMPLE,
244
- .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
245
- .communication_format = (i2s_comm_format_t )I2S_COMM_FORMAT_STAND_I2S,
246
- .intr_alloc_flags = 0 ,
247
- .dma_buf_count = DMA_BUF_COUNT,
248
- .dma_buf_len = DMA_BUF_LEN,
249
- .use_apll = true ,
250
- .tx_desc_auto_clear = true ,
251
- .fixed_mclk = mclk, // avoiding I2S bug
252
- };
253
- i2s_pin_config_t pin_config = {
254
- .bck_io_num = -1 ,
255
- .ws_io_num = -1 ,
256
- .data_out_num = cfg.pin_data ,
257
- .data_in_num = -1 ,
258
- };
259
-
260
- ESP_ERROR_CHECK (i2s_driver_install (I2S_NUM, &i2s_config, 0 , NULL ));
261
- ESP_ERROR_CHECK (i2s_set_pin (I2S_NUM, &pin_config));
262
- }
263
-
264
- size_t spdif_write (uint8_t *spdif_buf, size_t len) {
265
- size_t i2s_write_len;
266
- i2s_write (I2S_NUM, spdif_buf, len, &i2s_write_len, portMAX_DELAY);
267
- return i2s_write_len;
268
- }
269
-
270
- #else
271
- void spdif_init (SPDIFConfig &cfg) {
272
- int sample_rate = cfg.sample_rate * BMC_BITS_FACTOR;
273
- int bclk = sample_rate * I2S_BITS_PER_SAMPLE * I2S_CHANNELS;
274
- int mclk = (I2S_BUG_MAGIC / bclk) * bclk; // use mclk for avoiding I2S bug
275
-
276
- I2SConfig i2s_cfg;
277
- i2s_cfg.sample_rate = sample_rate;
278
- i2s_cfg.channels = cfg.channels ;
279
- i2s_cfg.bits_per_sample = 32 ;
280
- i2s_cfg.pin_ws = -1 ;
281
- i2s_cfg.pin_bck = -1 ;
282
- i2s_cfg.pin_data = cfg.pin_data ;
283
- i2s_cfg.use_apll = true ;
284
- i2s_cfg.fixed_mclk = mclk;
285
-
286
- i2s.begin (i2s_cfg);
287
- }
288
-
289
- size_t spdif_write (uint8_t *spdif_buf, size_t len) {
290
- return i2s.write (spdif_buf, len);
291
- }
292
-
293
- #endif
294
355
};
295
356
296
357
/* *
297
358
* @brief SPDIF Stream
298
- * We only support the output of different bits_per_sample and mono output
359
+ * We support the output of different bits_per_sample and mono output
299
360
* @author Phil Schatzmann
300
361
* @copyright GPLv3
301
362
*/
302
363
class SPDIFStream : public AudioStreamX {
303
364
public:
365
+ // / Default Constructor
304
366
SPDIFStream () = default ;
367
+
368
+ // / Constructor which is defining a specific output class
369
+ SPDIFStream (Print &out){
370
+ spdif_out = new SPDIFOutGeneric (out);
371
+ spdif.setOutput (spdif_out);
372
+ }
373
+
374
+ // /Destructor
375
+ ~SPDIFStream () {
376
+ end ();
377
+ if (spdif_out!=nullptr ){
378
+ delete spdif_out;
379
+ spdif_out = nullptr ;
380
+ }
381
+ }
382
+
305
383
// / start SPDIF with default configuration
306
384
bool begin () { spdif.begin (); }
307
385
// / start SPDIF with the indicated configuration
@@ -346,7 +424,8 @@ class SPDIFStream : public AudioStreamX {
346
424
protected:
347
425
SPDIFConfig cfg;
348
426
SPDIFStream16Bit2Channels spdif;
349
- FormatConverterStream converter {spdif};
427
+ FormatConverterStream converter{spdif};
428
+ SPDIFOutGeneric *spdif_out=nullptr ;
350
429
};
351
430
352
431
} // namespace audio_tools
0 commit comments