JackNetTool.cpp 52.1 KB
Newer Older
1
/*
sletz's avatar
sletz committed
2
Copyright (C) 2008-2011 Romain Moret at Grame
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/
sletz's avatar
sletz committed
19
20

#include "JackNetTool.h"
sletz's avatar
sletz committed
21
#include "JackError.h"
sletz's avatar
sletz committed
22

sletz's avatar
sletz committed
23
24
25
26
27
28
#ifdef __APPLE__

#include <mach/mach_time.h>

class HardwareClock
{
sletz's avatar
sletz committed
29
    public:
sletz's avatar
sletz committed
30

sletz's avatar
sletz committed
31
        HardwareClock();
sletz's avatar
sletz committed
32

sletz's avatar
sletz committed
33
34
        void Reset();
        void Update();
sletz's avatar
sletz committed
35

sletz's avatar
sletz committed
36
37
        float GetDeltaTime() const;
        double GetTime() const;
sletz's avatar
sletz committed
38

sletz's avatar
sletz committed
39
    private:
sletz's avatar
sletz committed
40

sletz's avatar
sletz committed
41
42
43
44
45
46
47
        double m_clockToSeconds;

        uint64_t m_startAbsTime;
        uint64_t m_lastAbsTime;

        double m_time;
        float m_deltaTime;
sletz's avatar
sletz committed
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
};

HardwareClock::HardwareClock()
{
	mach_timebase_info_data_t info;
	mach_timebase_info(&info);
	m_clockToSeconds = (double)info.numer/info.denom/1000000000.0;
	Reset();
}

void HardwareClock::Reset()
{
	m_startAbsTime = mach_absolute_time();
	m_lastAbsTime = m_startAbsTime;
	m_time = m_startAbsTime*m_clockToSeconds;
	m_deltaTime = 1.0f/60.0f;
}

void HardwareClock::Update()
{
	const uint64_t currentTime = mach_absolute_time();
	const uint64_t dt = currentTime - m_lastAbsTime;

	m_time = currentTime*m_clockToSeconds;
	m_deltaTime = (double)dt*m_clockToSeconds;
	m_lastAbsTime = currentTime;
}

float HardwareClock::GetDeltaTime() const
{
	return m_deltaTime;
}

double HardwareClock::GetTime() const
{
	return m_time;
}

#endif

sletz's avatar
sletz committed
88
89
90
91
92
93
using namespace std;

namespace Jack
{
// NetMidiBuffer**********************************************************************************

sletz's avatar
sletz committed
94
    NetMidiBuffer::NetMidiBuffer(session_params_t* params, uint32_t nports, char* net_buffer)
95
96
    {
        fNPorts = nports;
sletz's avatar
sletz committed
97
98
        fMaxBufsize = fNPorts * sizeof(sample_t) * params->fPeriodSize ;
        fMaxPcktSize = params->fMtu - sizeof(packet_header_t);
99
100
        fBuffer = new char[fMaxBufsize];
        fPortBuffer = new JackMidiBuffer* [fNPorts];
sletz's avatar
sletz committed
101
        for (int port_index = 0; port_index < fNPorts; port_index++) {
102
            fPortBuffer[port_index] = NULL;
sletz's avatar
sletz committed
103
        }
104
        fNetBuffer = net_buffer;
sletz's avatar
sletz committed
105

sletz's avatar
sletz committed
106
        fCycleBytesSize = params->fMtu
sletz's avatar
sletz committed
107
108
                * (max(params->fSendMidiChannels, params->fReturnMidiChannels)
                * params->fPeriodSize * sizeof(sample_t) / (params->fMtu - sizeof(packet_header_t)));
109
110
111
112
113
114
115
116
    }

    NetMidiBuffer::~NetMidiBuffer()
    {
        delete[] fBuffer;
        delete[] fPortBuffer;
    }

sletz's avatar
sletz committed
117
    size_t NetMidiBuffer::GetCycleSize()
118
    {
sletz's avatar
sletz committed
119
        return fCycleBytesSize;
sletz's avatar
sletz committed
120
    }
sletz's avatar
sletz committed
121

sletz's avatar
sletz committed
122
    int NetMidiBuffer::GetNumPackets(int data_size, int max_size)
sletz's avatar
sletz committed
123
    {
sletz's avatar
sletz committed
124
125
126
        int res1 = data_size % max_size;
        int res2 = data_size / max_size;
        return (res1) ? res2 + 1 : res2;
127
    }
128

sletz's avatar
sletz committed
129
    void NetMidiBuffer::SetBuffer(int index, JackMidiBuffer* buffer)
sletz's avatar
Cleanup    
sletz committed
130
131
132
    {
        fPortBuffer[index] = buffer;
    }
133

sletz's avatar
sletz committed
134
    JackMidiBuffer* NetMidiBuffer::GetBuffer(int index)
moret's avatar
moret committed
135
136
137
138
    {
        return fPortBuffer[index];
    }

139
140
    void NetMidiBuffer::DisplayEvents()
    {
141
142
        for (int port_index = 0; port_index < fNPorts; port_index++) {
            for (uint event = 0; event < fPortBuffer[port_index]->event_count; event++) {
sletz's avatar
sletz committed
143
                if (fPortBuffer[port_index]->IsValid()) {
sletz's avatar
sletz committed
144
                    jack_info("port %d : midi event %u/%u -> time : %u, size : %u",
145
                                port_index + 1, event + 1, fPortBuffer[port_index]->event_count,
sletz's avatar
sletz committed
146
                                fPortBuffer[port_index]->events[event].time, fPortBuffer[port_index]->events[event].size);
sletz's avatar
sletz committed
147
                }
148
            }
149
150
151
152
153
154
155
        }
    }

    int NetMidiBuffer::RenderFromJackPorts()
    {
        int pos = 0;
        size_t copy_size;
156
157

        for (int port_index = 0; port_index < fNPorts; port_index++) {
158
            char* write_pos = fBuffer + pos;
sletz's avatar
sletz committed
159
160
            copy_size = sizeof(JackMidiBuffer) + fPortBuffer[port_index]->event_count * sizeof(JackMidiEvent);
            memcpy(fBuffer + pos, fPortBuffer[port_index], copy_size);
161
            pos += copy_size;
sletz's avatar
sletz committed
162
163
164
            memcpy(fBuffer + pos,
                    fPortBuffer[port_index] + (fPortBuffer[port_index]->buffer_size - fPortBuffer[port_index]->write_pos),
                    fPortBuffer[port_index]->write_pos);
165
            pos += fPortBuffer[port_index]->write_pos;
166
167
            JackMidiBuffer* midi_buffer = reinterpret_cast<JackMidiBuffer*>(write_pos);
            MidiBufferHToN(midi_buffer, midi_buffer);
168
169
170
171
        }
        return pos;
    }

sletz's avatar
sletz committed
172
    void NetMidiBuffer::RenderToJackPorts()
173
174
    {
        int pos = 0;
sletz's avatar
sletz committed
175
        size_t copy_size;
176
177

        for (int port_index = 0; port_index < fNPorts; port_index++) {
178
179
            JackMidiBuffer* midi_buffer = reinterpret_cast<JackMidiBuffer*>(fBuffer + pos);
            MidiBufferNToH(midi_buffer, midi_buffer);
sletz's avatar
sletz committed
180
181
            copy_size = sizeof(JackMidiBuffer) + reinterpret_cast<JackMidiBuffer*>(fBuffer + pos)->event_count * sizeof(JackMidiEvent);
            memcpy(fPortBuffer[port_index], fBuffer + pos, copy_size);
182
            pos += copy_size;
sletz's avatar
sletz committed
183
            memcpy(fPortBuffer[port_index] + (fPortBuffer[port_index]->buffer_size - fPortBuffer[port_index]->write_pos),
sletz's avatar
sletz committed
184
185
                    fBuffer + pos,
                    fPortBuffer[port_index]->write_pos);
186
187
188
            pos += fPortBuffer[port_index]->write_pos;
        }
    }
189

190
    void NetMidiBuffer::RenderFromNetwork(int sub_cycle, size_t copy_size)
191
    {
192
        memcpy(fBuffer + sub_cycle * fMaxPcktSize, fNetBuffer, copy_size);
193
194
    }

195
    int NetMidiBuffer::RenderToNetwork(int sub_cycle, size_t total_size)
196
    {
197
        int size = total_size - sub_cycle * fMaxPcktSize;
sletz's avatar
sletz committed
198
        int copy_size = (size <= fMaxPcktSize) ? size : fMaxPcktSize;
199
        memcpy(fNetBuffer, fBuffer + sub_cycle * fMaxPcktSize, copy_size);
200
201
        return copy_size;
    }
sletz's avatar
sletz committed
202
203
204

// net audio buffer *********************************************************************************

sletz's avatar
sletz committed
205
206
207
208
    NetAudioBuffer::NetAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer)
    {
        fNPorts = nports;
        fNetBuffer = net_buffer;
Stephane Letz's avatar
Stephane Letz committed
209
        fNumPackets = 0;
sletz's avatar
sletz committed
210

211
        fPortBuffer = new sample_t*[fNPorts];
212
        fConnectedPorts = new bool[fNPorts];
213
        
sletz's avatar
sletz committed
214
        for (int port_index = 0; port_index < fNPorts; port_index++) {
215
216
            fPortBuffer[port_index] = NULL;
            fConnectedPorts[port_index] = true;
sletz's avatar
sletz committed
217
        }
218
219
220
221
222
223
224
        
        fLastSubCycle = 0;
        fPeriodSize = 0;
        fSubPeriodSize = 0;
        fSubPeriodBytesSize = 0;
        fCycleDuration = 0.f;
        fCycleBytesSize = 0;
sletz's avatar
sletz committed
225
    }
226
 
sletz's avatar
sletz committed
227
228
    NetAudioBuffer::~NetAudioBuffer()
    {
229
        delete [] fConnectedPorts;
sletz's avatar
sletz committed
230
231
232
233
234
235
236
237
238
239
240
241
242
        delete [] fPortBuffer;
    }

    void NetAudioBuffer::SetBuffer(int index, sample_t* buffer)
    {
        fPortBuffer[index] = buffer;
    }

    sample_t* NetAudioBuffer::GetBuffer(int index)
    {
        return fPortBuffer[index];
    }

sletz's avatar
sletz committed
243
244
245
246
247
248
    int NetAudioBuffer::CheckPacket(int cycle, int sub_cycle)
    {
        int res;

        if (sub_cycle != fLastSubCycle + 1) {
            jack_error("Packet(s) missing from... %d %d", fLastSubCycle, sub_cycle);
249
            res = DATA_PACKET_ERROR;
sletz's avatar
sletz committed
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
        } else {
            res = 0;
        }

        fLastSubCycle = sub_cycle;
        return res;
    }

    void NetAudioBuffer::NextCycle()
    {
        // reset for next cycle
        fLastSubCycle = -1;
    }

    void NetAudioBuffer::Cleanup()
    {
        for (int port_index = 0; port_index < fNPorts; port_index++) {
            if (fPortBuffer[port_index]) {
                memset(fPortBuffer[port_index], 0, fPeriodSize * sizeof(sample_t));
            }
        }
    }

sletz's avatar
sletz committed
273
274
    //network<->buffer

sletz's avatar
sletz committed
275
    int NetAudioBuffer::ActivePortsToNetwork(char* net_buffer)
sletz's avatar
sletz committed
276
    {
277
278
        int active_ports = 0;
        int* active_port_address = (int*)net_buffer;
sletz's avatar
sletz committed
279

sletz's avatar
sletz committed
280
281
282
        for (int port_index = 0; port_index < fNPorts; port_index++) {
            // Write the active port number
            if (fPortBuffer[port_index]) {
283
                *active_port_address = htonl(port_index);
sletz's avatar
sletz committed
284
                active_port_address++;
285
                active_ports++;
sletz's avatar
sletz committed
286
                assert(active_ports < 256); 
sletz's avatar
sletz committed
287
288
            }
        }
sletz's avatar
sletz committed
289

290
        return active_ports;
sletz's avatar
sletz committed
291
292
    }

sletz's avatar
sletz committed
293
    void NetAudioBuffer::ActivePortsFromNetwork(char* net_buffer, uint32_t port_num)
sletz's avatar
sletz committed
294
    {
295
        int* active_port_address = (int*)net_buffer;
296
  
sletz's avatar
sletz committed
297
        for (int port_index = 0; port_index < fNPorts; port_index++) {
298
            fConnectedPorts[port_index] = false;
sletz's avatar
sletz committed
299
300
301
        }

        for (uint port_index = 0; port_index < port_num; port_index++) {
302
            int active_port = ntohl(*active_port_address);
303
            fConnectedPorts[active_port] = true;
sletz's avatar
sletz committed
304
305
306
307
            active_port_address++;
        }
    }

308
    int NetAudioBuffer::RenderFromJackPorts(int unused_frames)
309
    {
sletz's avatar
sletz committed
310
311
312
313
314
315
316
        // Count active ports
        int active_ports = 0;
        for (int port_index = 0; port_index < fNPorts; port_index++) {
            if (fPortBuffer[port_index]) {
                active_ports++;
            }
        }
Stephane Letz's avatar
Stephane Letz committed
317
 
sletz's avatar
sletz committed
318
        return active_ports;
319
320
    }

321
    void NetAudioBuffer::RenderToJackPorts(int unused_frames)
322
    {
sletz's avatar
sletz committed
323
324
        // Nothing to do
        NextCycle();
325
326
    }

sletz's avatar
sletz committed
327
    // Float converter
sletz's avatar
sletz committed
328

sletz's avatar
sletz committed
329
    NetFloatAudioBuffer::NetFloatAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer)
sletz's avatar
sletz committed
330
        : NetAudioBuffer(params, nports, net_buffer)
sletz's avatar
sletz committed
331
332
    {
        fPeriodSize = params->fPeriodSize;
sletz's avatar
sletz committed
333
        fPacketSize = PACKET_AVAILABLE_SIZE(params);
sletz's avatar
sletz committed
334

sletz's avatar
sletz committed
335
        UpdateParams(max(params->fReturnAudioChannels, params->fSendAudioChannels));
sletz's avatar
sletz committed
336
337
338
339

        fSubPeriodBytesSize = fSubPeriodSize * sizeof(sample_t);

        fCycleDuration = float(fSubPeriodSize) / float(params->fSampleRate);
sletz's avatar
sletz committed
340
        fCycleBytesSize = params->fMtu * (fPeriodSize / fSubPeriodSize);
sletz's avatar
sletz committed
341
342
343
344

        fLastSubCycle = -1;
    }

sletz's avatar
sletz committed
345
    NetFloatAudioBuffer::~NetFloatAudioBuffer()
sletz's avatar
sletz committed
346
    {}
sletz's avatar
sletz committed
347
348

    // needed size in bytes for an entire cycle
sletz's avatar
sletz committed
349
    size_t NetFloatAudioBuffer::GetCycleSize()
sletz's avatar
sletz committed
350
    {
sletz's avatar
sletz committed
351
        return fCycleBytesSize;
sletz's avatar
sletz committed
352
353
354
    }

    // cycle duration in sec
sletz's avatar
sletz committed
355
    float NetFloatAudioBuffer::GetCycleDuration()
sletz's avatar
sletz committed
356
357
358
359
    {
        return fCycleDuration;
    }

sletz's avatar
sletz committed
360
    void NetFloatAudioBuffer::UpdateParams(int active_ports)
sletz's avatar
sletz committed
361
362
363
364
    {
        if (active_ports == 0) {
            fSubPeriodSize = fPeriodSize;
        } else {
365
            jack_nframes_t period = int(powf(2.f, int(log(float(fPacketSize) / (active_ports * sizeof(sample_t))) / log(2.))));
sletz's avatar
sletz committed
366
367
368
            fSubPeriodSize = (period > fPeriodSize) ? fPeriodSize : period;
        }

369
        fSubPeriodBytesSize = fSubPeriodSize * sizeof(sample_t) + sizeof(int); // The port number in coded on 4 bytes
Stephane Letz's avatar
Stephane Letz committed
370
        fNumPackets = fPeriodSize / fSubPeriodSize; // At least one packet
sletz's avatar
sletz committed
371
372
373
374
375
    }

    int NetFloatAudioBuffer::GetNumPackets(int active_ports)
    {
        UpdateParams(active_ports);
sletz's avatar
sletz committed
376
377

        /*
378
        jack_log("GetNumPackets packet = %d fPeriodSize = %d fSubPeriodSize = %d fSubPeriodBytesSize = %d",
sletz's avatar
sletz committed
379
380
            fPeriodSize / fSubPeriodSize, fPeriodSize, fSubPeriodSize, fSubPeriodBytesSize);
        */
Stephane Letz's avatar
Stephane Letz committed
381
        return fNumPackets;
sletz's avatar
sletz committed
382
383
384
385
    }

    //jack<->buffer

sletz's avatar
sletz committed
386
387
388
389
390
    int NetFloatAudioBuffer::RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num)
    {
        // Cleanup all JACK ports at the beginning of the cycle
        if (sub_cycle == 0) {
            Cleanup();
sletz's avatar
sletz committed
391
392
        }

sletz's avatar
sletz committed
393
394
395
396
        if (port_num > 0)  {
            UpdateParams(port_num);
            for (uint32_t port_index = 0; port_index < port_num; port_index++) {
                // Only copy to active ports : read the active port number then audio data
397
                int* active_port_address = (int*)(fNetBuffer + port_index * fSubPeriodBytesSize);
sletz's avatar
sletz committed
398
                int active_port = ntohl(*active_port_address);
399
                RenderFromNetwork((char*)(active_port_address + 1), active_port, sub_cycle);
sletz's avatar
sletz committed
400
401
402
403
            }
        }

        return CheckPacket(cycle, sub_cycle);
sletz's avatar
sletz committed
404
405
    }

sletz's avatar
sletz committed
406
407
    int NetFloatAudioBuffer::RenderToNetwork(int sub_cycle, uint32_t port_num)
    {
408
        int active_ports = 0;
sletz's avatar
sletz committed
409
410
411
412

        for (int port_index = 0; port_index < fNPorts; port_index++) {
            // Only copy from active ports : write the active port number then audio data
            if (fPortBuffer[port_index]) {
413
                int* active_port_address = (int*)(fNetBuffer + active_ports * fSubPeriodBytesSize);
sletz's avatar
sletz committed
414
                *active_port_address = htonl(port_index);
415
416
                RenderToNetwork((char*)(active_port_address + 1), port_index, sub_cycle);
                active_ports++;
sletz's avatar
sletz committed
417
418
419
420
421
422
            }
        }

        return port_num * fSubPeriodBytesSize;
    }

sletz's avatar
sletz committed
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
#ifdef __BIG_ENDIAN__

    static inline jack_default_audio_sample_t SwapFloat(jack_default_audio_sample_t f)
    {
          union
          {
            jack_default_audio_sample_t f;
            unsigned char b[4];
          } dat1, dat2;

          dat1.f = f;
          dat2.b[0] = dat1.b[3];
          dat2.b[1] = dat1.b[2];
          dat2.b[2] = dat1.b[1];
          dat2.b[3] = dat1.b[0];
          return dat2.f;
    }

    void NetFloatAudioBuffer::RenderFromNetwork(char* net_buffer, int active_port, int sub_cycle)
    {
        if (fPortBuffer[active_port]) {
            jack_default_audio_sample_t* src = (jack_default_audio_sample_t*)(net_buffer);
sletz's avatar
sletz committed
445
            jack_default_audio_sample_t* dst = (jack_default_audio_sample_t*)(fPortBuffer[active_port] + sub_cycle * fSubPeriodSize);
sletz's avatar
sletz committed
446
447
448
449
450
451
452
453
            for (unsigned int sample = 0; sample < (fSubPeriodBytesSize -  sizeof(int)) / sizeof(jack_default_audio_sample_t); sample++) {
                dst[sample] = SwapFloat(src[sample]);
            }
        }
    }

    void NetFloatAudioBuffer::RenderToNetwork(char* net_buffer, int active_port, int sub_cycle)
    {
sletz's avatar
sletz committed
454
        for (int port_index = 0; port_index < fNPorts; port_index++ ) {
sletz's avatar
sletz committed
455
456
457
458
459
460
461
462
463
464
            jack_default_audio_sample_t* src = (jack_default_audio_sample_t*)(fPortBuffer[active_port] + sub_cycle * fSubPeriodSize);
            jack_default_audio_sample_t* dst = (jack_default_audio_sample_t*)(net_buffer);
            for (unsigned int sample = 0; sample < (fSubPeriodBytesSize - sizeof(int)) / sizeof(jack_default_audio_sample_t); sample++) {
                dst[sample] = SwapFloat(src[sample]);
            }
        }
    }

#else

465
    void NetFloatAudioBuffer::RenderFromNetwork(char* net_buffer, int active_port, int sub_cycle)
sletz's avatar
sletz committed
466
    {
467
468
469
        if (fPortBuffer[active_port]) {
            memcpy(fPortBuffer[active_port] + sub_cycle * fSubPeriodSize, net_buffer, fSubPeriodBytesSize - sizeof(int));
        }
sletz's avatar
sletz committed
470
471
    }

472
    void NetFloatAudioBuffer::RenderToNetwork(char* net_buffer, int active_port, int sub_cycle)
sletz's avatar
sletz committed
473
    {
474
        memcpy(net_buffer, fPortBuffer[active_port] + sub_cycle * fSubPeriodSize, fSubPeriodBytesSize - sizeof(int));
sletz's avatar
sletz committed
475
476
    }

sletz's avatar
sletz committed
477
#endif
sletz's avatar
sletz committed
478
    // Celt audio buffer *********************************************************************************
sletz's avatar
sletz committed
479

nedko's avatar
nedko committed
480
#if HAVE_CELT
sletz's avatar
sletz committed
481
482
483
484

    #define KPS 32
    #define KPS_DIV 8

sletz's avatar
sletz committed
485
    NetCeltAudioBuffer::NetCeltAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer, int kbps)
sletz's avatar
sletz committed
486
        :NetAudioBuffer(params, nports, net_buffer)
487
    {
488
489
490
        fCeltMode = new CELTMode*[fNPorts];
        fCeltEncoder = new CELTEncoder*[fNPorts];
        fCeltDecoder = new CELTDecoder*[fNPorts];
sletz's avatar
sletz committed
491

sletz's avatar
sletz committed
492
493
494
        memset(fCeltMode, 0, fNPorts * sizeof(CELTMode*));
        memset(fCeltEncoder, 0, fNPorts * sizeof(CELTEncoder*));
        memset(fCeltDecoder, 0, fNPorts * sizeof(CELTDecoder*));
sletz's avatar
sletz committed
495

sletz's avatar
sletz committed
496
        int error = CELT_OK;
sletz's avatar
sletz committed
497

sletz's avatar
sletz committed
498
499
        for (int i = 0; i < fNPorts; i++)  {
            fCeltMode[i] = celt_mode_create(params->fSampleRate, params->fPeriodSize, &error);
sletz's avatar
sletz committed
500
            if (error != CELT_OK) {
501
                jack_log("NetCeltAudioBuffer celt_mode_create err = %d", error);
sletz's avatar
sletz committed
502
                goto error;
sletz's avatar
sletz committed
503
            }
sletz's avatar
sletz committed
504

sletz's avatar
sletz committed
505
506
507
    #if HAVE_CELT_API_0_11

            fCeltEncoder[i] = celt_encoder_create_custom(fCeltMode[i], 1, &error);
sletz's avatar
sletz committed
508
            if (error != CELT_OK) {
509
                jack_log("NetCeltAudioBuffer celt_encoder_create_custom err = %d", error);
sletz's avatar
sletz committed
510
                goto error;
sletz's avatar
sletz committed
511
            }
sletz's avatar
sletz committed
512
513
514
            celt_encoder_ctl(fCeltEncoder[i], CELT_SET_COMPLEXITY(1));

            fCeltDecoder[i] = celt_decoder_create_custom(fCeltMode[i], 1, &error);
sletz's avatar
sletz committed
515
            if (error != CELT_OK) {
516
                jack_log("NetCeltAudioBuffer celt_decoder_create_custom err = %d", error);
sletz's avatar
sletz committed
517
                goto error;
sletz's avatar
sletz committed
518
            }
sletz's avatar
sletz committed
519
520
521
522
            celt_decoder_ctl(fCeltDecoder[i], CELT_SET_COMPLEXITY(1));

    #elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8

sletz's avatar
sletz committed
523
            fCeltEncoder[i] = celt_encoder_create(fCeltMode[i], 1, &error);
sletz's avatar
sletz committed
524
            if (error != CELT_OK) {
525
                jack_log("NetCeltAudioBuffer celt_mode_create err = %d", error);
sletz's avatar
sletz committed
526
                goto error;
sletz's avatar
sletz committed
527
            }
sletz's avatar
sletz committed
528
            celt_encoder_ctl(fCeltEncoder[i], CELT_SET_COMPLEXITY(1));
sletz's avatar
sletz committed
529

sletz's avatar
sletz committed
530
            fCeltDecoder[i] = celt_decoder_create(fCeltMode[i], 1, &error);
sletz's avatar
sletz committed
531
            if (error != CELT_OK) {
532
                jack_log("NetCeltAudioBuffer celt_decoder_create err = %d", error);
sletz's avatar
sletz committed
533
                goto error;
sletz's avatar
sletz committed
534
            }
sletz's avatar
sletz committed
535
            celt_decoder_ctl(fCeltDecoder[i], CELT_SET_COMPLEXITY(1));
sletz's avatar
sletz committed
536
537
538
539

    #else

            fCeltEncoder[i] = celt_encoder_create(fCeltMode[i]);
sletz's avatar
sletz committed
540
            if (error != CELT_OK) {
541
                jack_log("NetCeltAudioBuffer celt_encoder_create err = %d", error);
sletz's avatar
sletz committed
542
                goto error;
sletz's avatar
sletz committed
543
            }
sletz's avatar
sletz committed
544
545
546
            celt_encoder_ctl(fCeltEncoder[i], CELT_SET_COMPLEXITY(1));

            fCeltDecoder[i] = celt_decoder_create(fCeltMode[i]);
sletz's avatar
sletz committed
547
            if (error != CELT_OK) {
548
                jack_log("NetCeltAudioBuffer celt_decoder_create err = %d", error);
sletz's avatar
sletz committed
549
                goto error;
sletz's avatar
sletz committed
550
            }
sletz's avatar
sletz committed
551
552
553
            celt_decoder_ctl(fCeltDecoder[i], CELT_SET_COMPLEXITY(1));

    #endif
sletz's avatar
sletz committed
554
        }
sletz's avatar
sletz committed
555

sletz's avatar
sletz committed
556
557
        {
            fPeriodSize = params->fPeriodSize;
sletz's avatar
sletz committed
558

sletz's avatar
sletz committed
559
560
            fCompressedSizeByte = (kbps * params->fPeriodSize * 1024) / (params->fSampleRate * 8);
            jack_log("NetCeltAudioBuffer fCompressedSizeByte %d", fCompressedSizeByte);
sletz's avatar
sletz committed
561

sletz's avatar
sletz committed
562
563
564
            fCompressedBuffer = new unsigned char* [fNPorts];
            for (int port_index = 0; port_index < fNPorts; port_index++) {
                fCompressedBuffer[port_index] = new unsigned char[fCompressedSizeByte];
sletz's avatar
sletz committed
565
                memset(fCompressedBuffer[port_index], 0, fCompressedSizeByte * sizeof(char));
sletz's avatar
sletz committed
566
            }
sletz's avatar
sletz committed
567

sletz's avatar
sletz committed
568
569
            int res1 = (fNPorts * fCompressedSizeByte) % PACKET_AVAILABLE_SIZE(params);
            int res2 = (fNPorts * fCompressedSizeByte) / PACKET_AVAILABLE_SIZE(params);
sletz's avatar
sletz committed
570

sletz's avatar
sletz committed
571
            fNumPackets = (res1) ? (res2 + 1) : res2;
sletz's avatar
sletz committed
572

sletz's avatar
sletz committed
573
            jack_log("NetCeltAudioBuffer res1 = %d res2 = %d", res1, res2);
sletz's avatar
sletz committed
574

sletz's avatar
sletz committed
575
576
            fSubPeriodBytesSize = fCompressedSizeByte / fNumPackets;
            fLastSubPeriodBytesSize = fSubPeriodBytesSize + fCompressedSizeByte % fNumPackets;
sletz's avatar
sletz committed
577

sletz's avatar
sletz committed
578
            jack_log("NetCeltAudioBuffer fNumPackets = %d fSubPeriodBytesSize = %d, fLastSubPeriodBytesSize = %d", fNumPackets, fSubPeriodBytesSize, fLastSubPeriodBytesSize);
sletz's avatar
sletz committed
579

sletz's avatar
sletz committed
580
581
            fCycleDuration = float(fSubPeriodBytesSize / sizeof(sample_t)) / float(params->fSampleRate);
            fCycleBytesSize = params->fMtu * fNumPackets;
sletz's avatar
sletz committed
582

sletz's avatar
sletz committed
583
584
585
            fLastSubCycle = -1;
            return;
        }
sletz's avatar
sletz committed
586

sletz's avatar
sletz committed
587
    error:
sletz's avatar
sletz committed
588

sletz's avatar
sletz committed
589
590
        FreeCelt();
        throw std::bad_alloc();
591
592
    }

sletz's avatar
sletz committed
593
    NetCeltAudioBuffer::~NetCeltAudioBuffer()
594
    {
sletz's avatar
sletz committed
595
        FreeCelt();
sletz's avatar
sletz committed
596

597
        for (int port_index = 0; port_index < fNPorts; port_index++) {
sletz's avatar
sletz committed
598
            delete [] fCompressedBuffer[port_index];
599
        }
sletz's avatar
sletz committed
600

sletz's avatar
sletz committed
601
        delete [] fCompressedBuffer;
602
603
    }

sletz's avatar
sletz committed
604
    void NetCeltAudioBuffer::FreeCelt()
605
    {
sletz's avatar
sletz committed
606
        for (int i = 0; i < fNPorts; i++)  {
607
            if (fCeltEncoder[i]) {
sletz's avatar
sletz committed
608
                celt_encoder_destroy(fCeltEncoder[i]);
609
610
            }
            if (fCeltDecoder[i]) {
sletz's avatar
sletz committed
611
                celt_decoder_destroy(fCeltDecoder[i]);
612
613
            }
            if (fCeltMode[i]) {
sletz's avatar
sletz committed
614
                celt_mode_destroy(fCeltMode[i]);
615
            }
sletz's avatar
sletz committed
616
        }
sletz's avatar
sletz committed
617

sletz's avatar
sletz committed
618
619
620
621
622
623
624
        delete [] fCeltMode;
        delete [] fCeltEncoder;
        delete [] fCeltDecoder;
    }

    size_t NetCeltAudioBuffer::GetCycleSize()
    {
sletz's avatar
sletz committed
625
        return fCycleBytesSize;
sletz's avatar
sletz committed
626
    }
sletz's avatar
sletz committed
627

sletz's avatar
sletz committed
628
629
630
631
    float NetCeltAudioBuffer::GetCycleDuration()
    {
        return fCycleDuration;
    }
sletz's avatar
sletz committed
632

sletz's avatar
sletz committed
633
    int NetCeltAudioBuffer::GetNumPackets(int active_ports)
sletz's avatar
sletz committed
634
635
    {
        return fNumPackets;
636
    }
637

638
    int NetCeltAudioBuffer::RenderFromJackPorts(int nframes)
639
    {
sletz's avatar
sletz committed
640
        float buffer[BUFFER_SIZE_MAX];
641

sletz's avatar
sletz committed
642
        for (int port_index = 0; port_index < fNPorts; port_index++) {
sletz's avatar
sletz committed
643
644
            if (fPortBuffer[port_index]) {
                memcpy(buffer, fPortBuffer[port_index], fPeriodSize * sizeof(sample_t));
sletz's avatar
sletz committed
645
646
647
648
            } else {
                memset(buffer, 0, fPeriodSize * sizeof(sample_t));
            }
        #if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11
649
            //int res = celt_encode_float(fCeltEncoder[port_index], buffer, fPeriodSize, fCompressedBuffer[port_index], fCompressedSizeByte);
farwayer's avatar
farwayer committed
650
            int res = celt_encode_float(fCeltEncoder[port_index], buffer, nframes, fCompressedBuffer[port_index], fCompressedSizeByte);
sletz's avatar
sletz committed
651
652
653
654
655
        #else
            int res = celt_encode_float(fCeltEncoder[port_index], buffer, NULL, fCompressedBuffer[port_index], fCompressedSizeByte);
        #endif
            if (res != fCompressedSizeByte) {
                jack_error("celt_encode_float error fCompressedSizeByte = %d res = %d", fCompressedSizeByte, res);
sletz's avatar
sletz committed
656
657
            }
        }
sletz's avatar
sletz committed
658
659
660

        // All ports active
        return fNPorts;
661
662
    }

663
    void NetCeltAudioBuffer::RenderToJackPorts(int nframes)
664
    {
sletz's avatar
sletz committed
665
        for (int port_index = 0; port_index < fNPorts; port_index++) {
sletz's avatar
sletz committed
666
667
            if (fPortBuffer[port_index]) {
            #if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11
668
                //int res = celt_decode_float(fCeltDecoder[port_index], fCompressedBuffer[port_index], fCompressedSizeByte, fPortBuffer[port_index], fPeriodSize);
farwayer's avatar
farwayer committed
669
                int res = celt_decode_float(fCeltDecoder[port_index], fCompressedBuffer[port_index], fCompressedSizeByte, fPortBuffer[port_index], nframes);
sletz's avatar
sletz committed
670
671
672
673
674
675
            #else
                int res = celt_decode_float(fCeltDecoder[port_index], fCompressedBuffer[port_index], fCompressedSizeByte, fPortBuffer[port_index]);
            #endif
                if (res != CELT_OK) {
                    jack_error("celt_decode_float error fCompressedSizeByte = %d res = %d", fCompressedSizeByte, res);
                }
676
677
            }
        }
sletz's avatar
sletz committed
678

sletz's avatar
sletz committed
679
        NextCycle();
680
681
    }

sletz's avatar
sletz committed
682
    //network<->buffer
sletz's avatar
sletz committed
683
    int NetCeltAudioBuffer::RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num)
684
    {
sletz's avatar
sletz committed
685
686
687
688
689
        // Cleanup all JACK ports at the beginning of the cycle
        if (sub_cycle == 0) {
            Cleanup();
        }

690
        if (port_num > 0) {
Stephane Letz's avatar
Stephane Letz committed
691
692
693
        
            int sub_period_bytes_size;
            
sletz's avatar
sletz committed
694
695
            // Last packet of the cycle
            if (sub_cycle == fNumPackets - 1) {
Stephane Letz's avatar
Stephane Letz committed
696
                sub_period_bytes_size = fLastSubPeriodBytesSize;
sletz's avatar
sletz committed
697
            } else {
Stephane Letz's avatar
Stephane Letz committed
698
699
700
701
702
                sub_period_bytes_size = fSubPeriodBytesSize;
            }
            
            for (int port_index = 0; port_index < fNPorts; port_index++) {
                memcpy(fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize, fNetBuffer + port_index * sub_period_bytes_size, sub_period_bytes_size);
703
            }
704
        }
sletz's avatar
sletz committed
705

sletz's avatar
sletz committed
706
        return CheckPacket(cycle, sub_cycle);
707
    }
708

sletz's avatar
sletz committed
709
    int NetCeltAudioBuffer::RenderToNetwork(int sub_cycle, uint32_t port_num)
sletz's avatar
sletz committed
710
    {
Stephane Letz's avatar
Stephane Letz committed
711
712
        int sub_period_bytes_size;
        
713
        // Last packet of the cycle
714
        if (sub_cycle == fNumPackets - 1) {
Stephane Letz's avatar
Stephane Letz committed
715
            sub_period_bytes_size = fLastSubPeriodBytesSize;
sletz's avatar
sletz committed
716
        } else {
Stephane Letz's avatar
Stephane Letz committed
717
718
719
720
721
            sub_period_bytes_size = fSubPeriodBytesSize;
        }
        
        for (int port_index = 0; port_index < fNPorts; port_index++) {
            memcpy(fNetBuffer + port_index * sub_period_bytes_size, fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize, sub_period_bytes_size);
sletz's avatar
sletz committed
722
        }
Stephane Letz's avatar
Stephane Letz committed
723
        return fNPorts * sub_period_bytes_size;
sletz's avatar
sletz committed
724
725
726
    }

#endif
moret's avatar
moret committed
727

728

Robin Gareus's avatar
Robin Gareus committed
729
#if HAVE_OPUS
730
#define CDO (sizeof(short)) ///< compressed data offset (first 2 bytes are length)
Robin Gareus's avatar
Robin Gareus committed
731
732
733
    NetOpusAudioBuffer::NetOpusAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer, int kbps)
        :NetAudioBuffer(params, nports, net_buffer)
    {
734
735
736
        fOpusMode = new OpusCustomMode*[fNPorts];
        fOpusEncoder = new OpusCustomEncoder*[fNPorts];
        fOpusDecoder = new OpusCustomDecoder*[fNPorts];
737
        fCompressedSizesByte = new unsigned short[fNPorts];
Robin Gareus's avatar
Robin Gareus committed
738
739
740
741

        memset(fOpusMode, 0, fNPorts * sizeof(OpusCustomMode*));
        memset(fOpusEncoder, 0, fNPorts * sizeof(OpusCustomEncoder*));
        memset(fOpusDecoder, 0, fNPorts * sizeof(OpusCustomDecoder*));
742
        memset(fCompressedSizesByte, 0, fNPorts * sizeof(short));
Robin Gareus's avatar
Robin Gareus committed
743
744

        int error = OPUS_OK;
745
        
Robin Gareus's avatar
Robin Gareus committed
746
747
        for (int i = 0; i < fNPorts; i++)  {
            /* Allocate en/decoders */
748
            fOpusMode[i] = opus_custom_mode_create(params->fSampleRate, params->fPeriodSize, &error);
Robin Gareus's avatar
Robin Gareus committed
749
            if (error != OPUS_OK) {
750
                jack_log("NetOpusAudioBuffer opus_custom_mode_create err = %d", error);
Robin Gareus's avatar
Robin Gareus committed
751
752
753
                goto error;
            }

754
            fOpusEncoder[i] = opus_custom_encoder_create(fOpusMode[i], 1, &error);
Robin Gareus's avatar
Robin Gareus committed
755
            if (error != OPUS_OK) {
756
                jack_log("NetOpusAudioBuffer opus_custom_encoder_create err = %d", error);
Robin Gareus's avatar
Robin Gareus committed
757
758
759
760
761
                goto error;
            }

            fOpusDecoder[i] = opus_custom_decoder_create(fOpusMode[i], 1, &error);
            if (error != OPUS_OK) {
762
                jack_log("NetOpusAudioBuffer opus_custom_decoder_create err = %d", error);
Robin Gareus's avatar
Robin Gareus committed
763
764
765
766
767
768
769
770
771
772
                goto error;
            }

            opus_custom_encoder_ctl(fOpusEncoder[i], OPUS_SET_BITRATE(kbps*1024)); // bits per second
            opus_custom_encoder_ctl(fOpusEncoder[i], OPUS_SET_COMPLEXITY(10));
            opus_custom_encoder_ctl(fOpusEncoder[i], OPUS_SET_SIGNAL(OPUS_SIGNAL_MUSIC));
            opus_custom_encoder_ctl(fOpusEncoder[i], OPUS_SET_SIGNAL(OPUS_APPLICATION_RESTRICTED_LOWDELAY));
        }

        {
773
            fCompressedMaxSizeByte = (kbps * params->fPeriodSize * 1024) / (params->fSampleRate * 8);
Robin Gareus's avatar
Robin Gareus committed
774
            fPeriodSize = params->fPeriodSize;
775
            jack_log("NetOpusAudioBuffer fCompressedMaxSizeByte %d", fCompressedMaxSizeByte);
Robin Gareus's avatar
Robin Gareus committed
776
777
778

            fCompressedBuffer = new unsigned char* [fNPorts];
            for (int port_index = 0; port_index < fNPorts; port_index++) {
779
780
                fCompressedBuffer[port_index] = new unsigned char[fCompressedMaxSizeByte];
                memset(fCompressedBuffer[port_index], 0, fCompressedMaxSizeByte * sizeof(char));
Robin Gareus's avatar
Robin Gareus committed
781
782
            }

783
784
            int res1 = (fNPorts * fCompressedMaxSizeByte + CDO) % PACKET_AVAILABLE_SIZE(params);
            int res2 = (fNPorts * fCompressedMaxSizeByte + CDO) / PACKET_AVAILABLE_SIZE(params);
Robin Gareus's avatar
Robin Gareus committed
785
786
787
788
789

            fNumPackets = (res1) ? (res2 + 1) : res2;

            jack_log("NetOpusAudioBuffer res1 = %d res2 = %d", res1, res2);

790
791
792
            fSubPeriodBytesSize = (fCompressedMaxSizeByte + CDO) / fNumPackets;
            fLastSubPeriodBytesSize = fSubPeriodBytesSize + (fCompressedMaxSizeByte + CDO) % fNumPackets;

Stephane Letz's avatar
Stephane Letz committed
793
794
795
            if (fNumPackets == 1) {
                fSubPeriodBytesSize = fLastSubPeriodBytesSize;
            }
Robin Gareus's avatar
Robin Gareus committed
796
797
798
799
800
801
802

            jack_log("NetOpusAudioBuffer fNumPackets = %d fSubPeriodBytesSize = %d, fLastSubPeriodBytesSize = %d", fNumPackets, fSubPeriodBytesSize, fLastSubPeriodBytesSize);

            fCycleDuration = float(fSubPeriodBytesSize / sizeof(sample_t)) / float(params->fSampleRate);
            fCycleBytesSize = params->fMtu * fNumPackets;

            fLastSubCycle = -1;
Stephane Letz's avatar
Stephane Letz committed
803
            return; 
Robin Gareus's avatar
Robin Gareus committed
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
        }

    error:

        FreeOpus();
        throw std::bad_alloc();
    }

    NetOpusAudioBuffer::~NetOpusAudioBuffer()
    {
        FreeOpus();

        for (int port_index = 0; port_index < fNPorts; port_index++) {
            delete [] fCompressedBuffer[port_index];
        }

        delete [] fCompressedBuffer;
821
        delete [] fCompressedSizesByte;
Robin Gareus's avatar
Robin Gareus committed
822
823
824
825
826
827
828
    }

    void NetOpusAudioBuffer::FreeOpus()
    {
        for (int i = 0; i < fNPorts; i++)  {
            if (fOpusEncoder[i]) {
                opus_custom_encoder_destroy(fOpusEncoder[i]);
829
                fOpusEncoder[i] = 0;
Robin Gareus's avatar
Robin Gareus committed
830
831
832
            }
            if (fOpusDecoder[i]) {
                opus_custom_decoder_destroy(fOpusDecoder[i]);
833
                fOpusDecoder[i] = 0;
Robin Gareus's avatar
Robin Gareus committed
834
835
836
            }
            if (fOpusMode[i]) {
                opus_custom_mode_destroy(fOpusMode[i]);
837
                fOpusMode[i] = 0;
Robin Gareus's avatar
Robin Gareus committed
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
            }
        }

        delete [] fOpusEncoder;
        delete [] fOpusDecoder;
        delete [] fOpusMode;
    }

    size_t NetOpusAudioBuffer::GetCycleSize()
    {
        return fCycleBytesSize;
    }

    float NetOpusAudioBuffer::GetCycleDuration()
    {
        return fCycleDuration;
    }

    int NetOpusAudioBuffer::GetNumPackets(int active_ports)
    {
        return fNumPackets;
    }

861
    int NetOpusAudioBuffer::RenderFromJackPorts(int nframes)
Robin Gareus's avatar
Robin Gareus committed
862
863
    {
        float buffer[BUFFER_SIZE_MAX];
864
      
Robin Gareus's avatar
Robin Gareus committed
865
866
867
868
869
870
        for (int port_index = 0; port_index < fNPorts; port_index++) {
            if (fPortBuffer[port_index]) {
                memcpy(buffer, fPortBuffer[port_index], fPeriodSize * sizeof(sample_t));
            } else {
                memset(buffer, 0, fPeriodSize * sizeof(sample_t));
            }
871
            int res = opus_custom_encode_float(fOpusEncoder[port_index], buffer, ((nframes == -1) ? fPeriodSize : nframes), fCompressedBuffer[port_index], fCompressedMaxSizeByte);
872
            if (res < 0 || res >= 65535) {
Stephane Letz's avatar
Stephane Letz committed
873
                jack_error("opus_custom_encode_float error res = %d", res);
Stephane Letz's avatar
Stephane Letz committed
874
875
876
877
                fCompressedSizesByte[port_index] = 0;
            } else {
                fCompressedSizesByte[port_index] = res;
            }
Robin Gareus's avatar
Robin Gareus committed
878
879
880
881
882
883
        }

        // All ports active
        return fNPorts;
    }

884
    void NetOpusAudioBuffer::RenderToJackPorts(int nframes)
Robin Gareus's avatar
Robin Gareus committed
885
886
887
    {
        for (int port_index = 0; port_index < fNPorts; port_index++) {
            if (fPortBuffer[port_index]) {
888
889
                int res = opus_custom_decode_float(fOpusDecoder[port_index], fCompressedBuffer[port_index], fCompressedSizesByte[port_index], fPortBuffer[port_index], ((nframes == -1) ? fPeriodSize : nframes));
                if (res < 0 || res != ((nframes == -1) ? fPeriodSize : nframes)) {
Stephane Letz's avatar
Stephane Letz committed
890
                    jack_error("opus_custom_decode_float error fCompressedSizeByte = %d res = %d", fCompressedSizesByte[port_index], res);
Robin Gareus's avatar
Robin Gareus committed
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
                }
            }
        }

        NextCycle();
    }

    //network<->buffer
    int NetOpusAudioBuffer::RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num)
    {
        // Cleanup all JACK ports at the beginning of the cycle
        if (sub_cycle == 0) {
            Cleanup();
        }

        if (port_num > 0)  {
907
            if (sub_cycle == 0) {
Robin Gareus's avatar
Robin Gareus committed
908
                for (int port_index = 0; port_index < fNPorts; port_index++) {
909
                    size_t len = *((size_t*)(fNetBuffer + port_index * fSubPeriodBytesSize));
910
                    fCompressedSizesByte[port_index] = ntohs(len);
911
912
913
914
915
                    memcpy(fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize, fNetBuffer + CDO + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize - CDO);
                }
            } else if (sub_cycle == fNumPackets - 1) {
                for (int port_index = 0; port_index < fNPorts; port_index++) {
                    memcpy(fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize - CDO, fNetBuffer + port_index * fLastSubPeriodBytesSize, fLastSubPeriodBytesSize);
Robin Gareus's avatar
Robin Gareus committed
916
917
918
                }
            } else {
                for (int port_index = 0; port_index < fNPorts; port_index++) {
919
                    memcpy(fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize - CDO, fNetBuffer + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize);
Robin Gareus's avatar
Robin Gareus committed
920
921
922
923
924
925
926
927
928
                }
            }
        }

        return CheckPacket(cycle, sub_cycle);
    }

    int NetOpusAudioBuffer::RenderToNetwork(int sub_cycle, uint32_t port_num)
    {
929
        if (sub_cycle == 0) {
Robin Gareus's avatar
Robin Gareus committed
930
            for (int port_index = 0; port_index < fNPorts; port_index++) {
931
                unsigned short len = htons(fCompressedSizesByte[port_index]);
932
933
934
935
936
937
938
                memcpy(fNetBuffer + port_index * fSubPeriodBytesSize, &len, CDO);
                memcpy(fNetBuffer + port_index * fSubPeriodBytesSize + CDO, fCompressedBuffer[port_index], fSubPeriodBytesSize - CDO);
            }
            return fNPorts * fSubPeriodBytesSize;
        } else if (sub_cycle == fNumPackets - 1) {
            for (int port_index = 0; port_index < fNPorts; port_index++) {
                memcpy(fNetBuffer + port_index * fLastSubPeriodBytesSize, fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize - CDO, fLastSubPeriodBytesSize);
Robin Gareus's avatar
Robin Gareus committed
939
940
941
942
            }
            return fNPorts * fLastSubPeriodBytesSize;
        } else {
            for (int port_index = 0; port_index < fNPorts; port_index++) {
943
                memcpy(fNetBuffer + port_index * fSubPeriodBytesSize, fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize - CDO, fSubPeriodBytesSize);
Robin Gareus's avatar
Robin Gareus committed
944
945
946
947
948
949
950
            }
            return fNPorts * fSubPeriodBytesSize;
        }
    }

#endif