1 //*****************************************************************
2 /*
3 JackTrip: A System for High-Quality Audio Network Performance
4 over the Internet
5
6 Copyright (c) 2008 Juan-Pablo Caceres, Chris Chafe.
7 SoundWIRE group at CCRMA, Stanford University.
8
9 Permission is hereby granted, free of charge, to any person
10 obtaining a copy of this software and associated documentation
11 files (the "Software"), to deal in the Software without
12 restriction, including without limitation the rights to use,
13 copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the
15 Software is furnished to do so, subject to the following
16 conditions:
17
18 The above copyright notice and this permission notice shall be
19 included in all copies or substantial portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 OTHER DEALINGS IN THE SOFTWARE.
29 */
30 //*****************************************************************
31
32 /**
33 * \file AudioInterface.cpp
34 * \author Juan-Pablo Caceres
35 * \date July 2009
36 */
37
38 #include "AudioInterface.h"
39 #include "JackTrip.h"
40 #include <iostream>
41 #include <cmath>
42 #include <assert.h>
43
44 using std::cout; using std::endl;
45
46 //*******************************************************************************
AudioInterface(JackTrip * jacktrip,int NumInChans,int NumOutChans,int NumNetRevChans,audioBitResolutionT AudioBitResolution)47 AudioInterface::AudioInterface(JackTrip* jacktrip,
48 int NumInChans, int NumOutChans,
49 #ifdef WAIR // wair
50 int NumNetRevChans,
51 #endif // endwhere
52 audioBitResolutionT AudioBitResolution) :
53 mJackTrip(jacktrip),
54 mNumInChans(NumInChans), mNumOutChans(NumOutChans),
55 #ifdef WAIR // WAIR
56 mNumNetRevChans(NumNetRevChans),
57 #endif // endwhere
58 mAudioBitResolution(AudioBitResolution*8),
59 mBitResolutionMode(AudioBitResolution),
60 mSampleRate(gDefaultSampleRate), mBufferSizeInSamples(gDefaultBufferSizeInSamples),
61 mInputPacket(NULL), mOutputPacket(NULL), mLoopBack(false), mProcessingAudio(false)
62 {
63 #ifndef WAIR
64 //cc
65 // Initialize and assign memory for ProcessPlugins Buffers
66 mInProcessBuffer.resize(mNumInChans);
67 mOutProcessBuffer.resize(mNumOutChans);
68 // Set pointer to NULL
69 for (int i = 0; i < mNumInChans; i++) {
70 mInProcessBuffer[i] = NULL;
71 }
72 for (int i = 0; i < mNumOutChans; i++) {
73 mOutProcessBuffer[i] = NULL;
74 }
75 #else // WAIR
76 int iCnt = (mNumInChans > mNumNetRevChans) ? mNumInChans : mNumNetRevChans;
77 int oCnt = (mNumOutChans > mNumNetRevChans) ? mNumOutChans : mNumNetRevChans;
78 int aCnt = (mNumNetRevChans) ? mNumInChans : 0;
79 for (int i = 0; i < iCnt; i++) {
80 mInProcessBuffer[i] = NULL;
81 }
82 for (int i = 0; i < oCnt; i++) {
83 mOutProcessBuffer[i] = NULL;
84 }
85 for (int i = 0; i < aCnt; i++) {
86 mAPInBuffer[i] = NULL;
87 }
88 #endif // endwhere
89
90 mInBufCopy.resize(mNumInChans);
91 for (int i=0; i<mNumInChans; i++) {
92 mInBufCopy[i] = new sample_t[MAX_AUDIO_BUFFER_SIZE]; // required for processing audio input
93 }
94 }
95
96
97 //*******************************************************************************
~AudioInterface()98 AudioInterface::~AudioInterface()
99 {
100 delete[] mInputPacket;
101 delete[] mOutputPacket;
102 #ifndef WAIR // NOT WAIR:
103 for (int i = 0; i < mNumInChans; i++) {
104 delete[] mInProcessBuffer[i];
105 }
106
107 for (int i = 0; i < mNumOutChans; i++) {
108 delete[] mOutProcessBuffer[i];
109 }
110 #else // WAIR
111 int iCnt = (mNumInChans > mNumNetRevChans) ? mNumInChans : mNumNetRevChans;
112 int oCnt = (mNumOutChans > mNumNetRevChans) ? mNumOutChans : mNumNetRevChans;
113 int aCnt = (mNumNetRevChans) ? mNumInChans : 0;
114 for (int i = 0; i < iCnt; i++) {
115 delete[] mInProcessBuffer[i];
116 }
117 for (int i = 0; i < oCnt; i++) {
118 delete[] mOutProcessBuffer[i];
119 }
120 for (int i = 0; i < aCnt; i++) {
121 delete[] mAPInBuffer[i];
122 }
123 #endif // endwhere
124
125 for (int i = 0; i < mProcessPluginsFromNetwork.size(); i++) {
126 delete mProcessPluginsFromNetwork[i];
127 }
128 for (int i = 0; i < mProcessPluginsToNetwork.size(); i++) {
129 delete mProcessPluginsToNetwork[i];
130 }
131 for (int i=0; i<mNumInChans; i++) {
132 delete mInBufCopy[i];
133 }
134 }
135
136
137 //*******************************************************************************
setup()138 void AudioInterface::setup()
139 {
140 // Allocate buffer memory to read and write
141 mSizeInBytesPerChannel = getSizeInBytesPerChannel();
142
143 int size_input = mSizeInBytesPerChannel * getNumInputChannels();
144 int size_output = mSizeInBytesPerChannel * getNumOutputChannels();
145 #ifdef WAIR // WAIR
146 if(mNumNetRevChans) // else don't change sizes
147 {
148 size_input = mSizeInBytesPerChannel * mNumNetRevChans;
149 size_output = mSizeInBytesPerChannel * mNumNetRevChans;
150 }
151 #endif // endwhere
152 mInputPacket = new int8_t[size_input];
153 mOutputPacket = new int8_t[size_output];
154
155 // Initialize and asign memory for ProcessPlugins Buffers
156 #ifdef WAIR // WAIR
157 if(mNumNetRevChans)
158 {
159 mInProcessBuffer.resize(mNumNetRevChans);
160 mOutProcessBuffer.resize(mNumNetRevChans);
161 mAPInBuffer.resize(mNumInChans);
162 mNetInBuffer.resize(mNumNetRevChans);
163 } else // don't change sizes
164 #endif // endwhere
165 {
166 mInProcessBuffer.resize(mNumInChans);
167 mOutProcessBuffer.resize(mNumOutChans);
168 }
169
170 int nframes = getBufferSizeInSamples();
171
172 #ifndef WAIR // NOT WAIR:
173 for (int i = 0; i < mNumInChans; i++) {
174 mInProcessBuffer[i] = new sample_t[nframes];
175 // set memory to 0
176 std::memset(mInProcessBuffer[i], 0, sizeof(sample_t) * nframes);
177 }
178 for (int i = 0; i < mNumOutChans; i++) {
179 mOutProcessBuffer[i] = new sample_t[nframes];
180 // set memory to 0
181 std::memset(mOutProcessBuffer[i], 0, sizeof(sample_t) * nframes);
182 }
183 #else // WAIR
184 for (int i = 0; i < ((mNumNetRevChans)?mNumNetRevChans:mNumInChans); i++) {
185 mInProcessBuffer[i] = new sample_t[nframes];
186 // set memory to 0
187 std::memset(mInProcessBuffer[i], 0, sizeof(sample_t) * nframes);
188 }
189 for (int i = 0; i < ((mNumNetRevChans)?mNumNetRevChans:mNumOutChans); i++) {
190 mOutProcessBuffer[i] = new sample_t[nframes];
191 // set memory to 0
192 std::memset(mOutProcessBuffer[i], 0, sizeof(sample_t) * nframes);
193 }
194 for (int i = 0; i < ((mNumNetRevChans)?mNumInChans:0); i++) {
195 mAPInBuffer[i] = new sample_t[nframes];
196 // set memory to 0
197 std::memset(mAPInBuffer[i], 0, sizeof(sample_t) * nframes);
198 }
199 for (int i = 0; i < mNumNetRevChans; i++) {
200 mNetInBuffer[i] = new sample_t[nframes];
201 // set memory to 0
202 std::memset(mNetInBuffer[i], 0, sizeof(sample_t) * nframes);
203 }
204 #endif // endwhere
205
206 }
207
208
209 //*******************************************************************************
getSizeInBytesPerChannel() const210 size_t AudioInterface::getSizeInBytesPerChannel() const
211 {
212 return (getBufferSizeInSamples() * getAudioBitResolution()/8);
213 }
214
215
216 //*******************************************************************************
callback(QVarLengthArray<sample_t * > & in_buffer,QVarLengthArray<sample_t * > & out_buffer,unsigned int n_frames)217 void AudioInterface::callback(QVarLengthArray<sample_t*>& in_buffer,
218 QVarLengthArray<sample_t*>& out_buffer,
219 unsigned int n_frames)
220 {
221 // Allocate the Process Callback
222 //-------------------------------------------------------------------
223 // 1) First, process incoming packets
224 // ----------------------------------
225
226 #ifdef WAIR // WAIR
227 // qDebug() << "--" << mProcessPluginsFromNetwork.size();
228 bool client = (mProcessPluginsFromNetwork.size() == 2);
229 #define COMBDSP 1 // client
230 #define APDSP 0 // client
231 #define DCBDSP 0 // server
232 for (int i = 0; i < mNumNetRevChans; i++) {
233 std::memset(mNetInBuffer[i], 0, sizeof(sample_t) * n_frames);
234 }
235 #endif // endwhere
236
237 // ==== RECEIVE AUDIO CHANNELS FROM NETWORK ====
238 computeProcessFromNetwork(out_buffer, n_frames);
239 // =============================================
240
241 // out_buffer is from the network and goes "out" to local audio
242 // hardware via JACK:
243
244 // mAudioTesterP will be nullptr for hub server's JackTripWorker instances
245 if (mAudioTesterP && mAudioTesterP->getEnabled()) {
246 mAudioTesterP->lookForReturnPulse(out_buffer, n_frames);
247 }
248
249 #ifdef WAIR // WAIR
250 // nib16 result now in mNetInBuffer
251 #endif // endwhere
252
253 // 2) Dynamically allocate ProcessPlugin processes
254 // -----------------------------------------------
255 // The processing will be done in order of allocation
256 /// \todo Implement for more than one process plugin, now it just works propertely with one.
257 /// do it chaining outputs to inputs in the buffers. May need a tempo buffer
258
259 #ifndef WAIR // NOT WAIR:
260 for (int i = 0; i < mProcessPluginsFromNetwork.size(); i++) {
261 ProcessPlugin* p = mProcessPluginsFromNetwork[i];
262 if (p->getInited()) {
263 p->compute(n_frames, out_buffer.data(), out_buffer.data());
264 }
265 }
266 #else // WAIR:
267 for (int i = 0; i < ((mNumNetRevChans)?mNumNetRevChans:mNumOutChans); i++) {
268 std::memset(mOutProcessBuffer[i], 0, sizeof(sample_t) * n_frames);
269 }
270 for (int i = 0; i < ((mNumNetRevChans)?mNumNetRevChans:mNumInChans); i++) {
271 std::memset(mInProcessBuffer[i], 0, sizeof(sample_t) * n_frames);
272 if (mNumNetRevChans)
273 {
274 if (client)
275 std::memcpy(mInProcessBuffer[i], mNetInBuffer[i], sizeof(sample_t) * n_frames);
276 else
277 std::memcpy(mOutProcessBuffer[i], mNetInBuffer[i], sizeof(sample_t) * n_frames);
278 }
279 }
280 // nib16 to cib16
281
282 if (mNumNetRevChans && client) {
283 mProcessPluginsFromNetwork[COMBDSP]->compute(n_frames, mInProcessBuffer.data(), mOutProcessBuffer.data());
284 }
285 // compute cob16
286 #endif // endwhere
287
288 // 3) Send packets to network:
289 // mAudioTesterP will be nullptr for hub server's JackTripWorker instances:
290 bool audioTesting = (mAudioTesterP && mAudioTesterP->getEnabled());
291 int nop = mProcessPluginsToNetwork.size(); // number of OUTGOING processing modules
292 if (nop>0 || audioTesting) { // cannot modify in_buffer, so make a copy
293 // in_buffer is "in" from local audio hardware via JACK
294 if (mInBufCopy.size() < mNumInChans) { // created in constructor above
295 std::cerr << "*** AudioInterface.cpp: Number of Input Channels changed - insufficient room reserved\n";
296 exit(1);
297 }
298 if (MAX_AUDIO_BUFFER_SIZE < n_frames) { // allocated in constructor above
299 std::cerr << "*** AudioInterface.cpp: n_frames = " << n_frames
300 << " larger than expected max = " << MAX_AUDIO_BUFFER_SIZE << "\n";
301 exit(1);
302 }
303 for (int i=0; i<mNumInChans; i++) {
304 std::memcpy(mInBufCopy[i], in_buffer[i], sizeof(sample_t) * n_frames);
305 }
306 for (int i = 0; i < nop; i++) {
307 // process all outgoing channels with ProcessPlugins:
308 ProcessPlugin* p = mProcessPluginsToNetwork[i];
309 if (p->getInited()) {
310 p->compute(n_frames, mInBufCopy.data(), mInBufCopy.data());
311 }
312 }
313 if (audioTesting) {
314 mAudioTesterP->writeImpulse(mInBufCopy, n_frames); // writes last channel of mInBufCopy with test impulse
315 }
316 computeProcessToNetwork(mInBufCopy, n_frames);
317 } else { // copy saved if no plugins and no audio testing in progress:
318 computeProcessToNetwork(in_buffer, n_frames); // send processed input audio to network - OUTGOING
319 }
320
321 #ifdef WAIR // WAIR
322 // aib2 + cob16 to nob16
323 #endif // endwhere
324
325 #ifdef WAIR // WAIR
326 if (mNumNetRevChans) // else not wair, so skip all this
327 {
328 ///////////////////////////////////////////////////////////////////////////////
329 #define AP
330 #ifndef AP
331 // straight to audio out
332 for (int i = 0; i < mNumOutChans; i++) {
333 std::memset(out_buffer[i], 0, sizeof(sample_t) * n_frames);
334 }
335 for (int i = 0; i < mNumNetRevChans; i++) {
336 sample_t* mix_sample = out_buffer[i%mNumOutChans];
337 sample_t* tmp_sample = mNetInBuffer[i]; //mNetInBuffer
338 for (int j = 0; j < (int)n_frames; j++) {mix_sample[j] += tmp_sample[j];}
339 } // nib6 to aob2
340 ///////////////////////////////////////////////////////////////////////////////
341 #else // AP
342 ///////////////////////////////////////////////////////////////////////////////
343 // output through all-pass cascade
344 // AP2 is 2 channel, mixes inputs to mono, then splits to two parallel AP chains
345 // AP8 is 2 channel, two parallel AP chains
346 for (int i = 0; i < mNumInChans; i++) {
347 std::memset(mAPInBuffer[i], 0, sizeof(sample_t) * n_frames);
348 }
349 for (int i = 0; i < mNumNetRevChans; i++) {
350 sample_t* mix_sample = mAPInBuffer[i%mNumOutChans];
351 sample_t* tmp_sample = mNetInBuffer[i];
352 for (int j = 0; j < n_frames; j++) {mix_sample[j] += tmp_sample[j];}
353 } // nib16 to apib2
354 for (int i = 0; i < mNumOutChans; i++) {
355 std::memset(out_buffer[i], 0, sizeof(sample_t) * n_frames);
356 }
357 mProcessPluginsFromNetwork[APDSP]->compute(n_frames, mAPInBuffer.data(), out_buffer.data());
358 // compute ap2 into aob2
359
360 //#define ADD_DIRECT
361 #ifdef ADD_DIRECT
362 for (int i = 0; i < mNumInChans; i++) {
363 sample_t* mix_sample = out_buffer[i];
364 sample_t* tmp_sample = in_buffer[i];
365 for (int j = 0; j < n_frames; j++) {mix_sample[j] += tmp_sample[j];}
366 }
367 // add aib2 to aob2
368 #endif // ADD_DIRECT
369 #endif // AP
370 ///////////////////////////////////////////////////////////////////////////////
371 }
372 #endif // endwhere
373
374 ///************PROTOTYPE FOR CELT**************************
375 ///********************************************************
376 /*
377 CELTMode* mode;
378 int* error;
379 mode = celt_mode_create(48000, 2, 64, error);
380 */
381 //celt_mode_create(48000, 2, 64, NULL);
382 //unsigned char* compressed;
383 //CELTEncoder* celtEncoder;
384 //celt_encode_float(celtEncoder, mInBuffer, NULL, compressed, );
385
386 ///********************************************************
387 ///********************************************************
388
389 }
390
391 //*******************************************************************************
broadcastCallback(QVarLengthArray<sample_t * > & mon_buffer,unsigned int n_frames)392 void AudioInterface::broadcastCallback(QVarLengthArray<sample_t*>& mon_buffer,
393 unsigned int n_frames)
394 {
395 /// \todo cast *mInBuffer[i] to the bit resolution
396 // Output Process (from NETWORK to JACK)
397 // ----------------------------------------------------------------
398 // Read Audio buffer from RingBuffer (read from incoming packets)
399 mJackTrip->receiveBroadcastPacket(mOutputPacket);
400 // Extract separate channels to send to Jack
401 for (int i = 0; i < mNumOutChans; i++) {
402 sample_t* tmp_sample = mon_buffer[i]; //sample buffer for channel i
403 for (unsigned int j = 0; j < n_frames; j++) {
404 // Change the bit resolution on each sample
405 fromBitToSampleConversion(
406 // use interleaved channel layout
407 //&mOutputPacket[(i*mSizeInBytesPerChannel) + (j*mBitResolutionMode)],
408 &mOutputPacket[(j*mBitResolutionMode*mNumOutChans) + (i*mBitResolutionMode)],
409 &tmp_sample[j], mBitResolutionMode );
410 }
411 }
412 }
413
414 //*******************************************************************************
415 // Before sending and reading to Jack, we have to round to the sample resolution
416 // that the program is using. Jack uses 32 bits (gJackBitResolution in globals.h)
417 // by default
computeProcessFromNetwork(QVarLengthArray<sample_t * > & out_buffer,unsigned int n_frames)418 void AudioInterface::computeProcessFromNetwork(QVarLengthArray<sample_t*>& out_buffer,
419 unsigned int n_frames)
420 {
421 /// \todo cast *mInBuffer[i] to the bit resolution
422 // Output Process (from NETWORK to JACK)
423 // ----------------------------------------------------------------
424 // Read Audio buffer from RingBuffer (read from incoming packets)
425 mJackTrip->receiveNetworkPacket( mOutputPacket );
426
427 #ifdef WAIR // WAIR
428 if (mNumNetRevChans)
429 // Extract separate channels
430 for (int i = 0; i < mNumNetRevChans; i++) {
431 sample_t* tmp_sample = mNetInBuffer[i]; //sample buffer for channel i
432 for (unsigned int j = 0; j < n_frames; j++) {
433 // Change the bit resolution on each sample
434 fromBitToSampleConversion(
435 // use interleaved channel layout
436 //&mOutputPacket[(i*mSizeInBytesPerChannel) + (j*mBitResolutionMode)],
437 &mOutputPacket[(j*mBitResolutionMode*mNumOutChans) + (i*mBitResolutionMode)],
438 &tmp_sample[j], mBitResolutionMode );
439 }
440 }
441 else // not wair
442 #endif // endwhere
443
444 // Extract separate channels to send to Jack
445 for (int i = 0; i < mNumOutChans; i++) {
446 //--------
447 // This should be faster for 32 bits
448 //std::memcpy(mOutBuffer[i], &mOutputPacket[i*mSizeInBytesPerChannel],
449 // mSizeInBytesPerChannel);
450 //--------
451 sample_t* tmp_sample = out_buffer[i]; //sample buffer for channel i
452 for (unsigned int j = 0; j < n_frames; j++) {
453 // Change the bit resolution on each sample
454 fromBitToSampleConversion(
455 // use interleaved channel layout
456 //&mOutputPacket[(i*mSizeInBytesPerChannel) + (j*mBitResolutionMode)],
457 &mOutputPacket[(j*mBitResolutionMode*mNumOutChans) + (i*mBitResolutionMode)],
458 &tmp_sample[j], mBitResolutionMode );
459 }
460 }
461 }
462
463
464 //*******************************************************************************
computeProcessToNetwork(QVarLengthArray<sample_t * > & in_buffer,unsigned int n_frames)465 void AudioInterface::computeProcessToNetwork(QVarLengthArray<sample_t*>& in_buffer,
466 unsigned int n_frames)
467 {
468 // Input Process (from JACK to NETWORK)
469 // ----------------------------------------------------------------
470 // Concatenate all the channels from jack to form packet
471
472 #ifdef WAIR // WAIR
473 if (mNumNetRevChans)
474 for (int i = 0; i < mNumNetRevChans; i++) {
475 sample_t* tmp_sample = in_buffer[i%mNumInChans]; //sample buffer for channel i
476 sample_t* tmp_process_sample = mOutProcessBuffer[i]; //sample buffer from the output process
477 sample_t tmp_result;
478 for (unsigned int j = 0; j < n_frames; j++) {
479 // Change the bit resolution on each sample
480 // Add the input jack buffer to the buffer resulting from the output process
481 #define INGAIN (0.9999) // 0.9999 because 1.0 can saturate the fixed pt rounding on output
482 #define COMBGAIN (1.0)
483 tmp_result = INGAIN*tmp_sample[j] + COMBGAIN*tmp_process_sample[j];
484 fromSampleToBitConversion(
485 &tmp_result,
486 // use interleaved channel layout
487 //&mInputPacket[(i*mSizeInBytesPerChannel) + (j*mBitResolutionMode)],
488 &mInputPacket[(j*mBitResolutionMode*mNumOutChans) + (i*mBitResolutionMode)],
489 mBitResolutionMode );
490 }
491 }
492 else // not wair
493 #endif // endwhere
494
495 for (int i = 0; i < mNumInChans; i++) {
496 //--------
497 // This should be faster for 32 bits
498 //std::memcpy(&mInputPacket[i*mSizeInBytesPerChannel], mInBuffer[i],
499 // mSizeInBytesPerChannel);
500 //--------
501 sample_t* tmp_sample = in_buffer[i]; //sample buffer for channel i
502 sample_t* tmp_process_sample = mOutProcessBuffer[i]; //sample buffer from the output process
503 sample_t tmp_result;
504 for (unsigned int j = 0; j < n_frames; j++) {
505 // Change the bit resolution on each sample
506 // Add the input jack buffer to the buffer resulting from the output process
507 tmp_result = tmp_sample[j] + tmp_process_sample[j];
508 fromSampleToBitConversion(
509 &tmp_result,
510 // use interleaved channel layout
511 //&mInputPacket[(i*mSizeInBytesPerChannel) + (j*mBitResolutionMode)],
512 &mInputPacket[(j*mBitResolutionMode*mNumOutChans) + (i*mBitResolutionMode)],
513 mBitResolutionMode );
514 }
515 }
516 // Send Audio buffer to Network
517 mJackTrip->sendNetworkPacket( mInputPacket );
518 } // /computeProcessToNetwork
519
520 //*******************************************************************************
521 // This function quantize from 32 bit to a lower bit resolution
522 // 24 bit is not working yet
fromSampleToBitConversion(const sample_t * const input,int8_t * output,const AudioInterface::audioBitResolutionT targetBitResolution)523 void AudioInterface::fromSampleToBitConversion
524 (const sample_t* const input,
525 int8_t* output,
526 const AudioInterface::audioBitResolutionT targetBitResolution)
527 {
528 int8_t tmp_8;
529 uint8_t tmp_u8; // unsigned to quantize the remainder in 24bits
530 int16_t tmp_16;
531 double tmp_sample;
532 sample_t tmp_sample16;
533 sample_t tmp_sample8;
534 switch (targetBitResolution)
535 {
536 case BIT8 :
537 // 8bit integer between -128 to 127
538 tmp_sample = std::max(-127.0, std::min(127.0, std::round( (*input) * 127.0 ))); // 2^7 = 128
539 tmp_8 = static_cast<int8_t>(tmp_sample);
540 std::memcpy(output, &tmp_8, 1); // 8bits = 1 bytes
541 break;
542 case BIT16 :
543 // 16bit integer between -32768 to 32767
544 // original scaling: tmp_sample = floor( (*input) * 32768.0 ); // 2^15 = 32768.0
545 tmp_sample = std::max(-32767.0, std::min(32767.0, std::round( (*input) * 32767.0 ))); // 2^15 = 32768
546 tmp_16 = static_cast<int16_t>(tmp_sample);
547 std::memcpy(output, &tmp_16, 2); // 2 bytes output in Little Endian order (LSB -> smallest address)
548 break;
549 case BIT24 :
550 // To convert to 24 bits, we first quantize the number to 16bit
551 tmp_sample = (*input) * 32768.0; // 2^15 = 32768.0
552 tmp_sample16 = floor(tmp_sample);
553 tmp_16 = static_cast<int16_t>(tmp_sample16);
554
555 // Then we compute the remainder error, and quantize that part into an 8bit number
556 // Note that this remainder is always positive, so we use an unsigned integer
557 tmp_sample8 = floor ((tmp_sample - tmp_sample16) //this is a positive number, between 0.0-1.0
558 * 256.0);
559 tmp_u8 = static_cast<uint8_t>(tmp_sample8);
560
561 // Finally, we copy the 16bit number in the first 2 bytes,
562 // and the 8bit number in the third bite
563 std::memcpy(output, &tmp_16, 2); // 16bits = 2 bytes
564 std::memcpy(output+2, &tmp_u8, 1); // 8bits = 1 bytes
565 break;
566 case BIT32 :
567 tmp_sample = *input;
568 // not necessary yet:
569 // tmp_sample = std::max(-1.0, std::min(1.0, tmp_sample));
570 std::memcpy(output, &tmp_sample, 4); // 32bit = 4 bytes
571 break;
572 }
573 }
574
575
576 //*******************************************************************************
fromBitToSampleConversion(const int8_t * const input,sample_t * output,const AudioInterface::audioBitResolutionT sourceBitResolution)577 void AudioInterface::fromBitToSampleConversion
578 (const int8_t* const input,
579 sample_t* output,
580 const AudioInterface::audioBitResolutionT sourceBitResolution)
581 {
582 int8_t tmp_8;
583 uint8_t tmp_u8;
584 int16_t tmp_16;
585 sample_t tmp_sample;
586 sample_t tmp_sample16;
587 sample_t tmp_sample8;
588 switch (sourceBitResolution)
589 {
590 case BIT8 :
591 tmp_8 = *input;
592 tmp_sample = static_cast<sample_t>(tmp_8) / 128.0;
593 std::memcpy(output, &tmp_sample, 4); // 4 bytes
594 break;
595 case BIT16 :
596 tmp_16 = *( reinterpret_cast<const int16_t*>(input) ); // *((int16_t*) input);
597 tmp_sample = static_cast<sample_t>(tmp_16) / 32768.0;
598 std::memcpy(output, &tmp_sample, 4); // 4 bytes
599 break;
600 case BIT24 :
601 // We first extract the 16bit and 8bit number from the 3 bytes
602 tmp_16 = *( reinterpret_cast<const int16_t*>(input) );
603 tmp_u8 = *( reinterpret_cast<const uint8_t*>(input+2) );
604
605 // Then we recover the number
606 tmp_sample16 = static_cast<sample_t>(tmp_16);
607 tmp_sample8 = static_cast<sample_t>(tmp_u8) / 256.0;
608 tmp_sample = (tmp_sample16 + tmp_sample8) / 32768.0;
609 std::memcpy(output, &tmp_sample, 4); // 4 bytes
610 break;
611 case BIT32 :
612 std::memcpy(output, input, 4); // 4 bytes
613 break;
614 }
615 }
616
617
618 //*******************************************************************************
appendProcessPluginToNetwork(ProcessPlugin * plugin)619 void AudioInterface::appendProcessPluginToNetwork(ProcessPlugin* plugin)
620 {
621 if (not plugin) { return; }
622 int nTestChans = (mAudioTesterP && mAudioTesterP->getEnabled()) ? 1 : 0;
623 int nPluginChans = mNumInChans - nTestChans;
624 assert(nTestChans==0 || (mAudioTesterP->getSendChannel() == mNumInChans-1));
625 if (plugin->getNumInputs() < nPluginChans) {
626 std::cerr << "*** AudioInterface.cpp: appendProcessPluginToNetwork: ProcessPlugin "
627 << typeid(plugin).name() << " REJECTED due to having "
628 << plugin->getNumInputs() << " inputs, while the audio to JACK needs "
629 << nPluginChans << " inputs\n";
630 return;
631 }
632 mProcessPluginsToNetwork.append(plugin);
633 }
634
appendProcessPluginFromNetwork(ProcessPlugin * plugin)635 void AudioInterface::appendProcessPluginFromNetwork(ProcessPlugin* plugin)
636 {
637 if (not plugin) { return; }
638 int nTestChans = (mAudioTesterP && mAudioTesterP->getEnabled()) ? 1 : 0;
639 int nPluginChans = mNumOutChans - nTestChans;
640 assert(nTestChans==0 || (mAudioTesterP->getSendChannel() == mNumOutChans-1));
641 if (plugin->getNumOutputs() > nPluginChans) {
642 std::cerr << "*** AudioInterface.cpp: appendProcessPluginFromNetwork: ProcessPlugin "
643 << typeid(plugin).name() << " REJECTED due to having "
644 << plugin->getNumOutputs() << " inputs, while the JACK audio output requires "
645 << nPluginChans << " outputs\n";
646 return;
647 }
648 mProcessPluginsFromNetwork.append(plugin);
649 }
650
initPlugins()651 void AudioInterface::initPlugins()
652 {
653 int nPlugins = mProcessPluginsFromNetwork.size() + mProcessPluginsToNetwork.size();
654 if (nPlugins > 0) {
655 std::cout << "Initializing Faust plugins (have " << nPlugins
656 << ") at sampling rate " << mSampleRate << "\n";
657 for (ProcessPlugin* plugin : mProcessPluginsFromNetwork) {
658 plugin->init(mSampleRate);
659 }
660 for (ProcessPlugin* plugin : mProcessPluginsToNetwork) {
661 plugin->init(mSampleRate);
662 }
663 }
664 }
665
666 //*******************************************************************************
getSampleRateType() const667 AudioInterface::samplingRateT AudioInterface::getSampleRateType() const
668 {
669 int32_t rate = getSampleRate();
670
671 if ( 100 > qAbs(rate - 22050) ) {
672 return AudioInterface::SR22; }
673 else if ( 100 > qAbs(rate - 32000) ) {
674 return AudioInterface::SR32; }
675 else if ( 100 > qAbs(rate - 44100) ) {
676 return AudioInterface::SR44; }
677 else if ( 100 > qAbs(rate - 48000) ) {
678 return AudioInterface::SR48; }
679 else if ( 100 > qAbs(rate - 88200) ) {
680 return AudioInterface::SR88; }
681 else if ( 100 > qAbs(rate - 96000) ) {
682 return AudioInterface::SR96; }
683 else if ( 100 > qAbs(rate - 19200) ) {
684 return AudioInterface::SR192; }
685
686 return AudioInterface::UNDEF;
687 }
688
689 //*******************************************************************************
getSampleRateFromType(samplingRateT rate_type)690 int AudioInterface::getSampleRateFromType(samplingRateT rate_type)
691 {
692 int sample_rate = 0;
693 switch (rate_type)
694 {
695 case SR22 :
696 sample_rate = 22050;
697 return sample_rate;
698 break;
699 case SR32 :
700 sample_rate = 32000;
701 return sample_rate;
702 break;
703 case SR44 :
704 sample_rate = 44100;
705 return sample_rate;
706 break;
707 case SR48 :
708 sample_rate = 48000;
709 return sample_rate;
710 break;
711 case SR88 :
712 sample_rate = 88200;
713 return sample_rate;
714 break;
715 case SR96 :
716 sample_rate = 96000;
717 return sample_rate;
718 break;
719 case SR192 :
720 sample_rate = 192000;
721 return sample_rate;
722 break;
723 default:
724 return sample_rate;
725 break;
726 }
727
728 return sample_rate;
729 }
730