Skip to content

Commit 9485518

Browse files
committed
ContainerOSC bug
1 parent 6d6625b commit 9485518

File tree

1 file changed

+83
-39
lines changed

1 file changed

+83
-39
lines changed

src/AudioTools/AudioCodecs/ContainerOSC.h

Lines changed: 83 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,8 @@
2222
namespace 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

Comments
 (0)