2222namespace audio_tools {
2323
2424/* *
25- * @brief Wraps the encoded data into OSC info and daata segments so that we
26- * can recover the audio configuration and orignial segments. We assume that a
27- * full segment is written with each call of write();
25+ * @brief Wraps the encoded data into OSC info and data segments so that the
26+ * receiver can recover the audio configuration and orignial segments.
2827 * @ingroup codecs
2928 * @ingroup encoder
3029 * @author Phil Schatzmann
@@ -37,17 +36,15 @@ class OSCContainerEncoder : public AudioEncoder {
3736
3837 void setEncoder (AudioEncoder *encoder) { p_codec = encoder; }
3938
40- void setOutput (Print &outStream) {
41- LOGD (" OSCContainerEncoder::setOutput" );
42- p_out = &outStream;
43- }
39+ void setOutput (Print &outStream) { p_out = &outStream; }
4440
4541 bool begin () override {
4642 TRACED ();
4743 if (p_codec == nullptr ) return false ;
48- // target.begin( );
49- is_active = p_codec->begin ( );
44+ osc_out. setOutput (*p_out );
45+ p_codec->setOutput (osc_out );
5046 p_codec->setAudioInfo (audioInfo ());
47+ is_active = p_codec->begin ();
5148 writeAudioInfo (audioInfo (), p_codec->mime ());
5249 return is_active;
5350 }
@@ -64,7 +61,7 @@ class OSCContainerEncoder : public AudioEncoder {
6461 if ((repeat_info > 0 ) && (packet_count % repeat_info == 0 )) {
6562 writeAudioInfo (audioInfo (), p_codec->mime ());
6663 }
67- writeAudio (data, len, packet_count );
64+ p_codec-> write (data, len);
6865 packet_count++;
6966 return len;
7067 }
@@ -78,53 +75,98 @@ class OSCContainerEncoder : public AudioEncoder {
7875
7976 virtual const char *mime () { return " audio/OSC" ; };
8077
78+ // / Activate/deactivate the sending of the audio info
79+ void setInfoActive (bool flag) { is_send_info_active = flag; }
80+ // / Automatically resend audio info ever nth write.
8181 void setRepeatInfoEvery (int packet_count) {
8282 this ->repeat_info = packet_count;
8383 }
8484
8585 // / Returns the sequence number of the next packet
86- uint64_t getSequenceNumber () { return packet_count ; }
87-
88- // / Writes the audio with the indicated sequence number to the output.
89- // / To be called to resend missing data
90- void writeAudio ( const uint8_t *data, size_t len, uint64_t sequenceNumber) {
91- LOGD ( " writeAudio: %d " , ( int )len);
92- uint8_t osc_data[len + 20 ]; // 20 is guess to cover address & fmt
93- OSCData osc{osc_data, sizeof (osc_data)};
94- osc. setAddress ( " /audio/data " );
95- osc. setFormat ( " ttb " );
96- osc. write (( uint64_t ) millis ());
97- // we use a uint64_t for a sequence number
98- osc. write (sequenceNumber);
99- osc. write ( data, len);
100- p_out-> write (osc_data, osc. size () );
86+ uint64_t getSequenceNumber () { return osc_out. getSequenceNumber () ; }
87+
88+ // / Define a reference object to be provided by the callback
89+ void setReference ( void *ref) { osc_out. setReference (ref); }
90+
91+ // / Get informed about the encoded packages
92+ void setEncodedWriteCallback ( void (*write_callback)( uint8_t *data, size_t len,
93+ uint64_t seq,
94+ void *ref)) {
95+ osc_out. setEncodedWriteCallback (write_callback );
96+ }
97+
98+ // / Resend the encoded data
99+ size_t resendEncodedData ( uint8_t * data, size_t len, uint64_t seq) {
100+ return osc_out. write (data, len, seq );
101101 }
102102
103103 protected:
104104 uint64_t packet_count = 0 ;
105105 int repeat_info = 0 ;
106106 bool is_active = false ;
107+ bool is_send_info_active = true ;
107108 AudioEncoder *p_codec = nullptr ;
108109 Print *p_out = nullptr ;
109110
111+ // / Output Encoded Audio via OSC
112+ class OSCOutput : public AudioOutput {
113+ public:
114+ void setReference (void *ref) { this ->ref = ref; }
115+ void setOutput (Print &outStream) { p_out = &outStream; }
116+ void setEncodedWriteCallback (void (*write_callback)(
117+ uint8_t *data, size_t len, uint64_t seq, void *ref)) {
118+ this ->encoded_write_callback = write_callback;
119+ }
120+ uint64_t getSequenceNumber () { return sequence_number; }
121+ size_t write (const uint8_t *data, size_t len) override {
122+ size_t result = write (data, len);
123+ sequence_number++;
124+ return result;
125+ }
126+ size_t write (const uint8_t *data, size_t len, uint64_t seq) {
127+ LOGD (" writeAudio: %d" , (int )len);
128+ if (encoded_write_callback != nullptr ) {
129+ encoded_write_callback ((uint8_t *)data, len, sequence_number, ref);
130+ }
131+ uint8_t osc_data[len + 20 ]; // 20 is guess to cover address & fmt
132+ OSCData osc{osc_data, sizeof (osc_data)};
133+ osc.setAddress (" /audio/data" );
134+ osc.setFormat (" ttb" );
135+ osc.write ((uint64_t )millis ());
136+ // we use a uint64_t for a sequence number
137+ osc.write (sequence_number);
138+ osc.write (data, len);
139+ p_out->write (osc_data, osc.size ());
140+ return len;
141+ }
142+
143+ protected:
144+ void (*encoded_write_callback)(uint8_t *data, size_t len, uint64_t seq,
145+ void *ref) = nullptr ;
146+ Print *p_out = nullptr ;
147+ uint64_t sequence_number = 0 ;
148+ void *ref = nullptr ;
149+ } osc_out;
110150
111151 void writeAudioInfo (AudioInfo info, const char *mime) {
112- LOGD (" writeAudioInfo" );
113- uint8_t osc_data[100 ];
114- OSCData osc{osc_data, sizeof (osc_data)};
115- osc.setAddress (" /audio/info" );
116- osc.setFormat (" iiis" );
117- osc.write ((int32_t )info.sample_rate );
118- osc.write ((int32_t )info.channels );
119- osc.write ((int32_t )info.bits_per_sample );
120- osc.write (mime);
121- p_out->write (osc_data, osc.size ());
152+ if (is_send_info_active) {
153+ LOGD (" writeAudioInfo" );
154+ uint8_t osc_data[100 ];
155+ OSCData osc{osc_data, sizeof (osc_data)};
156+ osc.setAddress (" /audio/info" );
157+ osc.setFormat (" iiis" );
158+ osc.write ((int32_t )info.sample_rate );
159+ osc.write ((int32_t )info.channels );
160+ osc.write ((int32_t )info.bits_per_sample );
161+ osc.write (mime);
162+ p_out->write (osc_data, osc.size ());
163+ }
122164 }
123165};
124166
125167/* *
126- * @brief Decodes the provided data from the OSC segments. I recommend to assign
127- * a MultiDecoder so that we can support muiltiple audio types.
168+ * @brief Decodes the provided data from the OSC segments. I recommend to
169+ * assign a MultiDecoder so that we can support muiltiple audio types.
128170 * @ingroup codecs
129171 * @ingroup decoder
130172 * @author Phil Schatzmann
@@ -192,7 +234,8 @@ class OSCContainerDecoder : public ContainerDecoder {
192234
193235 // / Callback to be called when data is missing
194236 void setMissingDataCallback (void (*missing_data_callback)(uint64_t from_seq,
195- uint64_t to_seq, void * ref)) {
237+ uint64_t to_seq,
238+ void *ref)) {
196239 this ->missing_data_callback = missing_data_callback;
197240 }
198241
@@ -216,7 +259,8 @@ class OSCContainerDecoder : public ContainerDecoder {
216259 void *ref = nullptr ;
217260
218261 // / Default callback for missing data: just log the missing range
219- static void missingDataCallback (uint64_t from_seq, uint64_t to_seq, void * ref) {
262+ static void missingDataCallback (uint64_t from_seq, uint64_t to_seq,
263+ void *ref) {
220264 LOGW (" Missing sequence numbers %d - %d" , from_seq, to_seq);
221265 }
222266
0 commit comments