Cleanup
[carla.git] / source / native-plugins / audio-base.hpp
blob41daded36caf4de581f87c3f066e167dd72faef4
1 /*
2 * Carla Native Plugins
3 * Copyright (C) 2013-2023 Filipe Coelho <falktx@falktx.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * For a full copy of the GNU General Public License see the GPL.txt file
18 #ifndef AUDIO_BASE_HPP_INCLUDED
19 #define AUDIO_BASE_HPP_INCLUDED
21 #include "CarlaMathUtils.hpp"
22 #include "CarlaMemUtils.hpp"
23 #include "CarlaRingBuffer.hpp"
25 extern "C" {
26 #include "audio_decoder/ad.h"
29 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
30 # pragma GCC diagnostic push
31 # pragma GCC diagnostic ignored "-Weffc++"
32 #endif
34 #include "zita-resampler/resampler.h"
36 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
37 # pragma GCC diagnostic pop
38 #endif
40 typedef struct adinfo ADInfo;
42 // --------------------------------------------------------------------------------------------------------------------
43 // tuning
45 // disk streaming buffer size
46 static constexpr const uint16_t kFileReaderBufferSize = 1024;
48 // if reading a file smaller than this, load it all in memory
49 static constexpr const uint16_t kMinLengthSeconds = 30;
51 // size of the audio file ring buffer
52 static constexpr const uint16_t kRingBufferLengthSeconds = 6;
54 static inline
55 constexpr float max4f(const float a, const float b, const float c, const float d) noexcept
57 return a > b && a > c && a > d ? a :
58 b > a && b > c && b > d ? b :
59 c > a && c > b && c > d ? c :
63 // --------------------------------------------------------------------------------------------------------------------
65 struct AudioMemoryPool {
66 float* buffer[2] = {};
67 uint32_t numFrames = 0;
68 CarlaMutex mutex;
70 AudioMemoryPool() noexcept {}
72 ~AudioMemoryPool() noexcept
74 destroy();
77 void create(const uint32_t desiredNumFrames)
79 CARLA_ASSERT(buffer[0] == nullptr);
80 CARLA_ASSERT(buffer[1] == nullptr);
81 CARLA_ASSERT(numFrames == 0);
83 buffer[0] = new float[desiredNumFrames];
84 buffer[1] = new float[desiredNumFrames];
85 carla_mlock(buffer[0], sizeof(float)*desiredNumFrames);
86 carla_mlock(buffer[1], sizeof(float)*desiredNumFrames);
88 const CarlaMutexLocker cml(mutex);
89 numFrames = desiredNumFrames;
92 void destroy() noexcept
95 const CarlaMutexLocker cml(mutex);
96 numFrames = 0;
99 if (buffer[0] != nullptr)
101 delete[] buffer[0];
102 buffer[0] = nullptr;
105 if (buffer[1] != nullptr)
107 delete[] buffer[1];
108 buffer[1] = nullptr;
112 CARLA_DECLARE_NON_COPYABLE(AudioMemoryPool)
115 // --------------------------------------------------------------------------------------------------------------------
117 class AudioFileReader
119 public:
120 enum QuadMode {
121 kQuad1and2,
122 kQuad3and4,
123 kQuadAll
126 AudioFileReader()
128 ad_clear_nfo(&fFileNfo);
131 ~AudioFileReader()
133 destroy();
136 void destroy()
138 const CarlaMutexLocker cml(fReaderMutex);
140 cleanup();
143 int getCurrentBitRate() const noexcept
145 return fCurrentBitRate;
148 float getLastPlayPosition() const noexcept
150 return fLastPlayPosition;
153 float getReadableBufferFill() const noexcept
155 if (fFileNfo.channels == 0)
156 return 0.f;
158 if (fEntireFileLoaded)
159 return 1.f;
161 return 1.f - (static_cast<float>(fRingBufferR.getReadableDataSize() / sizeof(float))
162 / static_cast<float>(fRingBufferR.getSize() / sizeof(float)));
165 ADInfo getFileInfo() const noexcept
167 return fFileNfo;
170 bool loadFilename(const char* const filename, const uint32_t sampleRate, const QuadMode quadMode,
171 const uint32_t previewDataSize, float* previewData)
173 CARLA_SAFE_ASSERT_RETURN(filename != nullptr && *filename != '\0', false);
175 const CarlaMutexLocker cml(fReaderMutex);
177 cleanup();
178 ad_clear_nfo(&fFileNfo);
180 // open new
181 fFilePtr = ad_open(filename, &fFileNfo);
183 if (fFilePtr == nullptr)
184 return false;
186 ad_dump_nfo(99, &fFileNfo);
188 // invalid
189 if ((fFileNfo.channels != 1 && fFileNfo.channels != 2 && fFileNfo.channels != 4) || fFileNfo.frames <= 0)
191 if (fFileNfo.channels != 1 && fFileNfo.channels != 2 && fFileNfo.channels != 4)
192 carla_stderr("loadFilename(\"%s\", ...) has not 1, 2 or 4 channels", filename);
194 if (fFileNfo.frames <= 0)
195 carla_stderr("loadFilename(\"%s\", ...) has 0 frames", filename);
197 ad_clear_nfo(&fFileNfo);
198 ad_close(fFilePtr);
199 fFilePtr = nullptr;
200 return false;
203 const uint64_t numFileFrames = static_cast<uint64_t>(fFileNfo.frames);
204 const bool needsResample = fFileNfo.sample_rate != sampleRate;
205 uint64_t numResampledFrames;
207 if (needsResample)
209 if (! fResampler.setup(fFileNfo.sample_rate, sampleRate, fFileNfo.channels, 32))
211 ad_clear_nfo(&fFileNfo);
212 ad_close(fFilePtr);
213 fFilePtr = nullptr;
214 carla_stderr2("loadFilename(\"%s\", ...) error, resampler setup failed");
215 return false;
218 fResampleRatio = static_cast<double>(sampleRate) / static_cast<double>(fFileNfo.sample_rate);
219 numResampledFrames = static_cast<uint64_t>(static_cast<double>(numFileFrames) * fResampleRatio + 0.5);
221 if (fPreviousResampledBuffer.buffer == nullptr)
222 fPreviousResampledBuffer.buffer = new float[kFileReaderBufferSize];
224 else
226 numResampledFrames = numFileFrames;
229 fQuadMode = quadMode;
231 if (fFileNfo.can_seek == 0 || numResampledFrames <= sampleRate * kMinLengthSeconds)
233 // read and cache the first few seconds of the file if seekable
234 const uint64_t initialFrames = fFileNfo.can_seek == 0
235 ? numFileFrames
236 : std::min<uint64_t>(numFileFrames, fFileNfo.sample_rate * kMinLengthSeconds);
237 const uint64_t initialResampledFrames = fFileNfo.can_seek == 0
238 ? numResampledFrames
239 : std::min<uint64_t>(numResampledFrames,
240 sampleRate * kMinLengthSeconds);
242 fInitialMemoryPool.create(initialResampledFrames);
243 readIntoInitialMemoryPool(initialFrames, initialResampledFrames);
245 // file is no longer needed, we have it all in memory
246 ad_close(fFilePtr);
247 fFilePtr = nullptr;
249 const float resampledFramesF = static_cast<float>(numResampledFrames);
250 const float previewDataSizeF = static_cast<float>(previewDataSize);
251 for (uint i=0; i<previewDataSize; ++i)
253 const float stepF = static_cast<float>(i)/previewDataSizeF * resampledFramesF;
254 const uint step = carla_fixedValue<uint64_t>(0, numResampledFrames-1, static_cast<uint>(stepF + 0.5f));
255 previewData[i] = std::max(std::fabs(fInitialMemoryPool.buffer[0][step]),
256 std::fabs(fInitialMemoryPool.buffer[1][step]));
259 fEntireFileLoaded = true;
261 else
263 readFilePreview(previewDataSize, previewData);
265 // cache only the first few initial seconds, let disk streaming handle the rest
266 const uint64_t initialFrames = std::min<uint64_t>(numFileFrames,
267 fFileNfo.sample_rate * kRingBufferLengthSeconds / 2);
268 const uint64_t initialResampledFrames = std::min<uint64_t>(numResampledFrames,
269 sampleRate * kRingBufferLengthSeconds / 2);
271 fRingBufferL.createBuffer(sampleRate * kRingBufferLengthSeconds * sizeof(float), true);
272 fRingBufferR.createBuffer(sampleRate * kRingBufferLengthSeconds * sizeof(float), true);
274 fInitialMemoryPool.create(initialResampledFrames);
275 readIntoInitialMemoryPool(initialFrames, initialResampledFrames);
277 fRingBufferL.writeCustomData(fInitialMemoryPool.buffer[0], fInitialMemoryPool.numFrames * sizeof(float));
278 fRingBufferR.writeCustomData(fInitialMemoryPool.buffer[1], fInitialMemoryPool.numFrames * sizeof(float));
279 fRingBufferL.commitWrite();
280 fRingBufferR.commitWrite();
282 fEntireFileLoaded = false;
285 fTotalResampledFrames = numResampledFrames;
286 fSampleRate = sampleRate;
288 return true;
291 bool tickFrames(float* const buffers[],
292 uint32_t bufferOffset, uint32_t frames, uint64_t framePos,
293 const bool loopingMode, const bool isOffline)
295 float* outL = buffers[0] + bufferOffset;
296 float* outR = buffers[1] + bufferOffset;
297 float* playCV = buffers[2] + bufferOffset;
299 if (loopingMode && framePos >= fTotalResampledFrames)
300 framePos %= fTotalResampledFrames;
302 if (framePos >= fTotalResampledFrames)
304 carla_zeroFloats(outL, frames);
305 carla_zeroFloats(outR, frames);
306 carla_zeroFloats(playCV, frames);
307 fLastPlayPosition = 1.f;
308 return false;
311 uint32_t numPoolFrames, usableFrames;
314 const CarlaMutexTryLocker cmtl(fInitialMemoryPool.mutex, isOffline);
316 numPoolFrames = fInitialMemoryPool.numFrames;
318 if (numPoolFrames == 0 || ! cmtl.wasLocked())
320 carla_zeroFloats(outL, frames);
321 carla_zeroFloats(outR, frames);
322 carla_zeroFloats(playCV, frames);
323 return false;
326 if (framePos < numPoolFrames)
328 usableFrames = std::min(frames, numPoolFrames - static_cast<uint32_t>(framePos));
330 carla_copyFloats(outL, fInitialMemoryPool.buffer[0] + framePos, usableFrames);
331 carla_copyFloats(outR, fInitialMemoryPool.buffer[1] + framePos, usableFrames);
332 carla_fillFloatsWithSingleValue(playCV, 10.f, usableFrames);
334 outL += usableFrames;
335 outR += usableFrames;
336 playCV += usableFrames;
337 bufferOffset += usableFrames;
338 framePos += usableFrames;
339 frames -= usableFrames;
342 if (fEntireFileLoaded && frames != 0)
343 return tickFrames(buffers, bufferOffset, frames, framePos, loopingMode, isOffline);
346 fLastPlayPosition = static_cast<float>(framePos / 64) / static_cast<float>(fTotalResampledFrames / 64);
348 if (fEntireFileLoaded)
349 return false;
351 if (frames == 0)
353 // ring buffer is good, waiting for data reads
354 if (fRingBufferFramePos == numPoolFrames)
355 return false;
357 // out of bounds, host likely has repositioned transport
358 if (fRingBufferFramePos > numPoolFrames)
360 fNextFileReadPos = 0;
361 return true;
364 // within bounds, skip frames until we reach the end of the memory pool
365 const uint32_t framesUpToPoolEnd = numPoolFrames - fRingBufferFramePos;
366 if (fRingBufferR.getReadableDataSize() / sizeof(float) >= framesUpToPoolEnd)
368 fRingBufferL.skipRead(framesUpToPoolEnd * sizeof(float));
369 fRingBufferR.skipRead(framesUpToPoolEnd * sizeof(float));
370 fRingBufferFramePos = numPoolFrames;
373 return true;
376 uint32_t totalFramesAvailable = fRingBufferR.getReadableDataSize() / sizeof(float);
378 if (framePos != fRingBufferFramePos)
380 // unaligned position, see if we need to relocate too
381 if (framePos < fRingBufferFramePos || framePos >= fRingBufferFramePos + totalFramesAvailable - frames)
383 carla_zeroFloats(outL, frames);
384 carla_zeroFloats(outR, frames);
385 carla_zeroFloats(playCV, frames);
387 // wait until the previous relocation is done
388 if (fNextFileReadPos == -1)
389 fNextFileReadPos = framePos - frames;
391 return true;
394 // oh nice, we can skip a few frames and be in sync
395 const uint32_t diffFrames = framePos - fRingBufferFramePos;
396 fRingBufferL.skipRead(diffFrames * sizeof(float));
397 fRingBufferR.skipRead(diffFrames * sizeof(float));
398 totalFramesAvailable -= diffFrames;
399 fRingBufferFramePos = framePos;
402 usableFrames = std::min<uint32_t>(frames, totalFramesAvailable);
404 if (usableFrames == 0)
406 carla_zeroFloats(outL, frames);
407 carla_zeroFloats(outR, frames);
408 carla_zeroFloats(playCV, frames);
409 return framePos < fTotalResampledFrames;
412 fRingBufferL.readCustomData(outL, usableFrames * sizeof(float));
413 fRingBufferR.readCustomData(outR, usableFrames * sizeof(float));
414 carla_fillFloatsWithSingleValue(playCV, 10.f, usableFrames);
416 fRingBufferFramePos += usableFrames;
417 totalFramesAvailable -= usableFrames;
419 if (frames != usableFrames)
421 if (loopingMode)
423 bufferOffset += usableFrames;
424 framePos += usableFrames;
425 frames -= usableFrames;
426 return tickFrames(buffers, bufferOffset, frames, framePos, loopingMode, isOffline);
429 carla_zeroFloats(outL + usableFrames, frames - usableFrames);
430 carla_zeroFloats(outR + usableFrames, frames - usableFrames);
431 carla_zeroFloats(playCV + usableFrames, frames - usableFrames);
434 return totalFramesAvailable <= fSampleRate * 2;
437 void readFilePreview(uint32_t previewDataSize, float* const previewData)
439 carla_zeroFloats(previewData, previewDataSize);
441 if (fFileNfo.can_seek == 0)
442 return;
444 const uint fileNumFrames = static_cast<uint>(fFileNfo.frames);
445 const float fileNumFramesF = static_cast<float>(fileNumFrames);
446 const float previewDataSizeF = static_cast<float>(previewDataSize);
447 const uint channels = fFileNfo.channels;
448 const uint samplesPerRun = channels * 4;
449 const uint maxSampleToRead = fileNumFrames - samplesPerRun;
450 const uint8_t quadoffs = fQuadMode == kQuad3and4 ? 2 : 0;
451 float tmp[16] = {};
453 for (uint i=0; i<previewDataSize; ++i)
455 const float posF = static_cast<float>(i)/previewDataSizeF * fileNumFramesF;
456 const uint pos = carla_fixedValue(0U, maxSampleToRead, static_cast<uint>(posF));
458 ad_seek(fFilePtr, pos);
459 ad_read(fFilePtr, tmp, samplesPerRun);
461 switch (channels)
463 case 1:
464 previewData[i] = max4f(std::fabs(tmp[0]),
465 std::fabs(tmp[1]),
466 std::fabs(tmp[2]),
467 std::fabs(tmp[3]));
468 break;
469 case 2:
470 previewData[i] = max4f(std::fabs(tmp[0]),
471 std::fabs(tmp[2]),
472 std::fabs(tmp[4]),
473 std::fabs(tmp[6]));
474 previewData[i] = std::max(previewData[i], max4f(std::fabs(tmp[1]),
475 std::fabs(tmp[3]),
476 std::fabs(tmp[5]),
477 std::fabs(tmp[7])));
478 break;
479 case 4:
480 if (fQuadMode == kQuadAll)
482 previewData[i] = max4f(std::fabs(tmp[0]) + std::fabs(tmp[4])
483 + std::fabs(tmp[8]) + std::fabs(tmp[12]),
484 std::fabs(tmp[1]) + std::fabs(tmp[5])
485 + std::fabs(tmp[9]) + std::fabs(tmp[13]),
486 std::fabs(tmp[2]) + std::fabs(tmp[6])
487 + std::fabs(tmp[10]) + std::fabs(tmp[14]),
488 std::fabs(tmp[3]) + std::fabs(tmp[7])
489 + std::fabs(tmp[11]) + std::fabs(tmp[15]));
491 else
493 previewData[i] = max4f(std::fabs(tmp[quadoffs+0]),
494 std::fabs(tmp[quadoffs+4]),
495 std::fabs(tmp[quadoffs+8]),
496 std::fabs(tmp[quadoffs+12]));
497 previewData[i] = std::max(previewData[i], max4f(std::fabs(tmp[quadoffs+1]),
498 std::fabs(tmp[quadoffs+5]),
499 std::fabs(tmp[quadoffs+9]),
500 std::fabs(tmp[quadoffs+13])));
502 break;
507 void readPoll()
509 const CarlaMutexLocker cml(fReaderMutex);
511 const uint channels = fFileNfo.channels;
513 if (channels == 0 || fFilePtr == nullptr)
515 carla_debug("R: no song loaded");
516 return;
519 fCurrentBitRate = ad_get_bitrate(fFilePtr);
521 const bool needsResample = carla_isNotEqual(fResampleRatio, 1.0);
522 const uint8_t quadoffs = fQuadMode == kQuad3and4 ? 2 : 0;
523 const int64_t nextFileReadPos = fNextFileReadPos;
525 if (nextFileReadPos != -1)
527 fRingBufferL.flush();
528 fRingBufferR.flush();
530 fPreviousResampledBuffer.frames = 0;
531 fRingBufferFramePos = nextFileReadPos;
532 ad_seek(fFilePtr, nextFileReadPos / fResampleRatio);
534 if (needsResample)
535 fResampler.reset();
538 if (needsResample)
540 float buffer[kFileReaderBufferSize];
541 float rbuffer[kFileReaderBufferSize];
542 ssize_t r;
543 uint prev_inp_count = 0;
545 while (fRingBufferR.getWritableDataSize() >= sizeof(rbuffer))
547 if (const uint32_t oldframes = fPreviousResampledBuffer.frames)
549 prev_inp_count = oldframes;
550 fPreviousResampledBuffer.frames = 0;
551 std::memcpy(buffer, fPreviousResampledBuffer.buffer, sizeof(float) * oldframes * channels);
553 else if (prev_inp_count != 0)
555 std::memmove(buffer,
556 buffer + (sizeof(buffer) / sizeof(float) - prev_inp_count * channels),
557 sizeof(float) * prev_inp_count * channels);
560 r = ad_read(fFilePtr,
561 buffer + (prev_inp_count * channels),
562 sizeof(buffer) / sizeof(float) - (prev_inp_count * channels));
564 if (r < 0)
566 carla_stderr("R: ad_read failed");
567 break;
570 if (r == 0)
571 break;
573 fResampler.inp_count = prev_inp_count + r / channels;
574 fResampler.out_count = sizeof(rbuffer) / sizeof(float) / channels;
575 fResampler.inp_data = buffer;
576 fResampler.out_data = rbuffer;
577 fResampler.process();
579 r = sizeof(rbuffer) / sizeof(float) - fResampler.out_count * channels;
581 if (fResampleRatio > 1.0)
583 if (fResampler.out_count == 0)
585 CARLA_SAFE_ASSERT_UINT(fResampler.inp_count != 0, fResampler.inp_count);
587 else
589 CARLA_SAFE_ASSERT_UINT(fResampler.inp_count == 0, fResampler.inp_count);
592 else
594 CARLA_SAFE_ASSERT(fResampler.inp_count == 0);
597 prev_inp_count = fResampler.inp_count;
599 if (r == 0)
600 break;
602 switch (channels)
604 case 1:
605 fRingBufferL.writeCustomData(rbuffer, r * sizeof(float));
606 fRingBufferR.writeCustomData(rbuffer, r * sizeof(float));
607 break;
608 case 2:
609 for (ssize_t i=0; i < r;)
611 fRingBufferL.writeCustomData(&rbuffer[i++], sizeof(float));
612 fRingBufferR.writeCustomData(&rbuffer[i++], sizeof(float));
614 break;
615 case 4:
616 if (fQuadMode == kQuadAll)
618 float v;
619 for (ssize_t i=0; i < r; i += 4)
621 v = rbuffer[i] + rbuffer[i+1] + rbuffer[i+2] + rbuffer[i+3];
622 fRingBufferL.writeCustomData(&v, sizeof(float));
623 fRingBufferR.writeCustomData(&v, sizeof(float));
626 else
628 for (ssize_t i=quadoffs; i < r; i += 4)
630 fRingBufferL.writeCustomData(&rbuffer[i], sizeof(float));
631 fRingBufferR.writeCustomData(&rbuffer[i+1], sizeof(float));
634 break;
637 fRingBufferL.commitWrite();
638 fRingBufferR.commitWrite();
641 if (prev_inp_count != 0)
643 fPreviousResampledBuffer.frames = prev_inp_count;
644 std::memcpy(fPreviousResampledBuffer.buffer,
645 buffer + (sizeof(buffer) / sizeof(float) - prev_inp_count * channels),
646 sizeof(float) * prev_inp_count * channels);
649 else
651 float buffer[kFileReaderBufferSize];
652 ssize_t r;
654 while (fRingBufferR.getWritableDataSize() >= sizeof(buffer))
656 r = ad_read(fFilePtr, buffer, sizeof(buffer)/sizeof(float));
658 if (r < 0)
660 carla_stderr("R: ad_read failed");
661 break;
664 if (r == 0)
665 break;
667 switch (channels)
669 case 1:
670 fRingBufferL.writeCustomData(buffer, r * sizeof(float));
671 fRingBufferR.writeCustomData(buffer, r * sizeof(float));
672 break;
673 case 2:
674 for (ssize_t i=0; i < r;)
676 fRingBufferL.writeCustomData(&buffer[i++], sizeof(float));
677 fRingBufferR.writeCustomData(&buffer[i++], sizeof(float));
679 break;
680 case 4:
681 if (fQuadMode == kQuadAll)
683 float v;
684 for (ssize_t i=0; i < r; i += 4)
686 v = buffer[i] + buffer[i+1] + buffer[i+2] + buffer[i+3];
687 fRingBufferL.writeCustomData(&v, sizeof(float));
688 fRingBufferR.writeCustomData(&v, sizeof(float));
691 else
693 for (ssize_t i=quadoffs; i < r; i += 4)
695 fRingBufferL.writeCustomData(&buffer[i], sizeof(float));
696 fRingBufferR.writeCustomData(&buffer[i+1], sizeof(float));
699 break;
702 fRingBufferL.commitWrite();
703 fRingBufferR.commitWrite();
707 if (nextFileReadPos != -1)
708 fNextFileReadPos = -1;
711 private:
712 bool fEntireFileLoaded = false;
713 QuadMode fQuadMode = kQuad1and2;
714 int fCurrentBitRate = 0;
715 float fLastPlayPosition = 0.f;
716 int64_t fNextFileReadPos = -1;
717 uint64_t fTotalResampledFrames = 0;
719 void* fFilePtr = nullptr;
720 ADInfo fFileNfo = {};
722 uint32_t fSampleRate = 0;
723 double fResampleRatio = 1.0;
725 AudioMemoryPool fInitialMemoryPool;
726 Resampler fResampler;
727 CarlaMutex fReaderMutex;
729 struct PreviousResampledBuffer {
730 float* buffer = nullptr;
731 uint32_t frames = 0;
732 } fPreviousResampledBuffer;
734 CarlaHeapRingBuffer fRingBufferL, fRingBufferR;
735 uint64_t fRingBufferFramePos = 0;
737 // assumes reader lock is active
738 void cleanup()
740 fEntireFileLoaded = false;
741 fCurrentBitRate = 0;
742 fLastPlayPosition = 0.f;
743 fNextFileReadPos = -1;
744 fTotalResampledFrames = 0;
745 fSampleRate = 0;
746 fRingBufferFramePos = 0;
747 fResampleRatio = 1.0;
749 fResampler.clear();
750 fInitialMemoryPool.destroy();
751 fRingBufferL.deleteBuffer();
752 fRingBufferR.deleteBuffer();
754 if (fFilePtr != nullptr)
756 ad_close(fFilePtr);
757 fFilePtr = nullptr;
760 delete[] fPreviousResampledBuffer.buffer;
761 fPreviousResampledBuffer.buffer = nullptr;
762 fPreviousResampledBuffer.frames = 0;
765 void readIntoInitialMemoryPool(const uint numFrames, const uint numResampledFrames)
767 const uint channels = fFileNfo.channels;
768 const uint fileBufferSize = numFrames * channels;
770 float* const fileBuffer = (float*)std::malloc(fileBufferSize * sizeof(float));
771 CARLA_SAFE_ASSERT_RETURN(fileBuffer != nullptr,);
773 ad_seek(fFilePtr, 0);
774 ssize_t rv = ad_read(fFilePtr, fileBuffer, fileBufferSize);
775 CARLA_SAFE_ASSERT_INT2_RETURN(rv == static_cast<ssize_t>(fileBufferSize),
776 rv, fileBufferSize,
777 std::free(fileBuffer));
779 fCurrentBitRate = ad_get_bitrate(fFilePtr);
781 float* resampledBuffer;
783 if (numFrames != numResampledFrames)
785 resampledBuffer = (float*)std::malloc(numResampledFrames * channels * sizeof(float));
786 CARLA_SAFE_ASSERT_RETURN(resampledBuffer != nullptr, std::free(fileBuffer););
788 fResampler.inp_count = numFrames;
789 fResampler.out_count = numResampledFrames;
790 fResampler.inp_data = fileBuffer;
791 fResampler.out_data = resampledBuffer;
792 fResampler.process();
794 fInitialMemoryPool.numFrames = numResampledFrames - fResampler.out_count;
795 rv = fInitialMemoryPool.numFrames * channels;
797 else
799 resampledBuffer = fileBuffer;
803 // lock, and put data asap
804 const CarlaMutexLocker cml(fInitialMemoryPool.mutex);
806 switch (channels)
808 case 1:
809 for (ssize_t i=0; i < rv; ++i)
810 fInitialMemoryPool.buffer[0][i] = fInitialMemoryPool.buffer[1][i] = resampledBuffer[i];
811 break;
812 case 2:
813 for (ssize_t i=0, j=0; i < rv; ++j)
815 fInitialMemoryPool.buffer[0][j] = resampledBuffer[i++];
816 fInitialMemoryPool.buffer[1][j] = resampledBuffer[i++];
818 break;
819 case 4:
820 if (fQuadMode == kQuadAll)
822 for (ssize_t i=0, j=0; i < rv; ++j)
824 fInitialMemoryPool.buffer[0][j] = fInitialMemoryPool.buffer[1][j]
825 = resampledBuffer[i] + resampledBuffer[i+1] + resampledBuffer[i+2] + resampledBuffer[i+3];
826 i += 4;
829 else
831 for (ssize_t i = fQuadMode == kQuad3and4 ? 2 : 0, j = 0; i < rv; ++j)
833 fInitialMemoryPool.buffer[0][j] = resampledBuffer[i];
834 fInitialMemoryPool.buffer[1][j] = resampledBuffer[i+1];
835 i += 4;
838 break;
842 if (resampledBuffer != fileBuffer)
843 std::free(resampledBuffer);
845 std::free(fileBuffer);
848 CARLA_DECLARE_NON_COPYABLE(AudioFileReader)
851 // --------------------------------------------------------------------------------------------------------------------
853 #endif // AUDIO_BASE_HPP_INCLUDED