/* Copyright (C) 2008-2011 Romain Moret at Grame 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. */ #include "JackNetCelt.h" #include "JackError.h" namespace Jack { #define KPS 32 #define KPS_DIV 8 NetCeltAudioBuffer::NetCeltAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer, int kbps) :NetAudioBuffer(params, nports, net_buffer) { fCeltMode = new CELTMode*[fNPorts]; fCeltEncoder = new CELTEncoder*[fNPorts]; fCeltDecoder = new CELTDecoder*[fNPorts]; memset(fCeltMode, 0, fNPorts * sizeof(CELTMode*)); memset(fCeltEncoder, 0, fNPorts * sizeof(CELTEncoder*)); memset(fCeltDecoder, 0, fNPorts * sizeof(CELTDecoder*)); int error = CELT_OK; for (int i = 0; i < fNPorts; i++) { fCeltMode[i] = celt_mode_create(params->fSampleRate, params->fPeriodSize, &error); if (error != CELT_OK) { jack_log("NetCeltAudioBuffer celt_mode_create err = %d", error); goto error; } #if HAVE_CELT_API_0_11 fCeltEncoder[i] = celt_encoder_create_custom(fCeltMode[i], 1, &error); if (error != CELT_OK) { jack_log("NetCeltAudioBuffer celt_encoder_create_custom err = %d", error); goto error; } celt_encoder_ctl(fCeltEncoder[i], CELT_SET_COMPLEXITY(1)); fCeltDecoder[i] = celt_decoder_create_custom(fCeltMode[i], 1, &error); if (error != CELT_OK) { jack_log("NetCeltAudioBuffer celt_decoder_create_custom err = %d", error); goto error; } celt_decoder_ctl(fCeltDecoder[i], CELT_SET_COMPLEXITY(1)); #elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 fCeltEncoder[i] = celt_encoder_create(fCeltMode[i], 1, &error); if (error != CELT_OK) { jack_log("NetCeltAudioBuffer celt_mode_create err = %d", error); goto error; } celt_encoder_ctl(fCeltEncoder[i], CELT_SET_COMPLEXITY(1)); fCeltDecoder[i] = celt_decoder_create(fCeltMode[i], 1, &error); if (error != CELT_OK) { jack_log("NetCeltAudioBuffer celt_decoder_create err = %d", error); goto error; } celt_decoder_ctl(fCeltDecoder[i], CELT_SET_COMPLEXITY(1)); #else fCeltEncoder[i] = celt_encoder_create(fCeltMode[i]); if (error != CELT_OK) { jack_log("NetCeltAudioBuffer celt_encoder_create err = %d", error); goto error; } celt_encoder_ctl(fCeltEncoder[i], CELT_SET_COMPLEXITY(1)); fCeltDecoder[i] = celt_decoder_create(fCeltMode[i]); if (error != CELT_OK) { jack_log("NetCeltAudioBuffer celt_decoder_create err = %d", error); goto error; } celt_decoder_ctl(fCeltDecoder[i], CELT_SET_COMPLEXITY(1)); #endif } { fPeriodSize = params->fPeriodSize; fCompressedSizeByte = (kbps * params->fPeriodSize * 1024) / (params->fSampleRate * 8); jack_log("NetCeltAudioBuffer fCompressedSizeByte %d", fCompressedSizeByte); fCompressedBuffer = new unsigned char* [fNPorts]; for (int port_index = 0; port_index < fNPorts; port_index++) { fCompressedBuffer[port_index] = new unsigned char[fCompressedSizeByte]; memset(fCompressedBuffer[port_index], 0, fCompressedSizeByte * sizeof(char)); } int res1 = (fNPorts * fCompressedSizeByte) % PACKET_AVAILABLE_SIZE(params); int res2 = (fNPorts * fCompressedSizeByte) / PACKET_AVAILABLE_SIZE(params); fNumPackets = (res1) ? (res2 + 1) : res2; jack_log("NetCeltAudioBuffer res1 = %d res2 = %d", res1, res2); fSubPeriodBytesSize = fCompressedSizeByte / fNumPackets; fLastSubPeriodBytesSize = fSubPeriodBytesSize + fCompressedSizeByte % fNumPackets; jack_log("NetCeltAudioBuffer fNumPackets = %d fSubPeriodBytesSize = %d, fLastSubPeriodBytesSize = %d", fNumPackets, fSubPeriodBytesSize, fLastSubPeriodBytesSize); fCycleDuration = float(fSubPeriodBytesSize / sizeof(sample_t)) / float(params->fSampleRate); fCycleBytesSize = params->fMtu * fNumPackets; fLastSubCycle = -1; return; } error: FreeCelt(); throw std::bad_alloc(); } NetCeltAudioBuffer::~NetCeltAudioBuffer() { FreeCelt(); for (int port_index = 0; port_index < fNPorts; port_index++) { delete [] fCompressedBuffer[port_index]; } delete [] fCompressedBuffer; } void NetCeltAudioBuffer::FreeCelt() { for (int i = 0; i < fNPorts; i++) { if (fCeltEncoder[i]) { celt_encoder_destroy(fCeltEncoder[i]); } if (fCeltDecoder[i]) { celt_decoder_destroy(fCeltDecoder[i]); } if (fCeltMode[i]) { celt_mode_destroy(fCeltMode[i]); } } delete [] fCeltMode; delete [] fCeltEncoder; delete [] fCeltDecoder; } size_t NetCeltAudioBuffer::GetCycleSize() { return fCycleBytesSize; } float NetCeltAudioBuffer::GetCycleDuration() { return fCycleDuration; } int NetCeltAudioBuffer::GetNumPackets(int active_ports) { return fNumPackets; } int NetCeltAudioBuffer::RenderFromJackPorts(int nframes) { float buffer[BUFFER_SIZE_MAX]; 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)); } #if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11 //int res = celt_encode_float(fCeltEncoder[port_index], buffer, fPeriodSize, fCompressedBuffer[port_index], fCompressedSizeByte); int res = celt_encode_float(fCeltEncoder[port_index], buffer, nframes, fCompressedBuffer[port_index], fCompressedSizeByte); #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); } } // All ports active return fNPorts; } void NetCeltAudioBuffer::RenderToJackPorts(int nframes) { for (int port_index = 0; port_index < fNPorts; port_index++) { if (fPortBuffer[port_index]) { #if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11 //int res = celt_decode_float(fCeltDecoder[port_index], fCompressedBuffer[port_index], fCompressedSizeByte, fPortBuffer[port_index], fPeriodSize); int res = celt_decode_float(fCeltDecoder[port_index], fCompressedBuffer[port_index], fCompressedSizeByte, fPortBuffer[port_index], nframes); #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); } } } NextCycle(); } //network<->buffer int NetCeltAudioBuffer::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) { int sub_period_bytes_size; // Last packet of the cycle if (sub_cycle == fNumPackets - 1) { sub_period_bytes_size = fLastSubPeriodBytesSize; } else { 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); } } return CheckPacket(cycle, sub_cycle); } int NetCeltAudioBuffer::RenderToNetwork(int sub_cycle, uint32_t port_num) { int sub_period_bytes_size; // Last packet of the cycle if (sub_cycle == fNumPackets - 1) { sub_period_bytes_size = fLastSubPeriodBytesSize; } else { 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); } return fNPorts * sub_period_bytes_size; } }