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"
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++"
34 #include "zita-resampler/resampler.h"
36 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
37 # pragma GCC diagnostic pop
40 typedef struct adinfo ADInfo
;
42 // --------------------------------------------------------------------------------------------------------------------
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;
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;
70 AudioMemoryPool() noexcept
{}
72 ~AudioMemoryPool() noexcept
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
);
99 if (buffer
[0] != nullptr)
105 if (buffer
[1] != nullptr)
112 CARLA_DECLARE_NON_COPYABLE(AudioMemoryPool
)
115 // --------------------------------------------------------------------------------------------------------------------
117 class AudioFileReader
128 ad_clear_nfo(&fFileNfo
);
138 const CarlaMutexLocker
cml(fReaderMutex
);
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)
158 if (fEntireFileLoaded
)
161 return 1.f
- (static_cast<float>(fRingBufferR
.getReadableDataSize() / sizeof(float))
162 / static_cast<float>(fRingBufferR
.getSize() / sizeof(float)));
165 ADInfo
getFileInfo() const noexcept
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
);
178 ad_clear_nfo(&fFileNfo
);
181 fFilePtr
= ad_open(filename
, &fFileNfo
);
183 if (fFilePtr
== nullptr)
186 ad_dump_nfo(99, &fFileNfo
);
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
);
203 const uint64_t numFileFrames
= static_cast<uint64_t>(fFileNfo
.frames
);
204 const bool needsResample
= fFileNfo
.sample_rate
!= sampleRate
;
205 uint64_t numResampledFrames
;
209 if (! fResampler
.setup(fFileNfo
.sample_rate
, sampleRate
, fFileNfo
.channels
, 32))
211 ad_clear_nfo(&fFileNfo
);
214 carla_stderr2("loadFilename(\"%s\", ...) error, resampler setup failed");
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
];
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
236 : std::min
<uint64_t>(numFileFrames
, fFileNfo
.sample_rate
* kMinLengthSeconds
);
237 const uint64_t initialResampledFrames
= fFileNfo
.can_seek
== 0
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
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;
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
;
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
;
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
);
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
)
353 // ring buffer is good, waiting for data reads
354 if (fRingBufferFramePos
== numPoolFrames
)
357 // out of bounds, host likely has repositioned transport
358 if (fRingBufferFramePos
> numPoolFrames
)
360 fNextFileReadPos
= 0;
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
;
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
;
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
)
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)
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;
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
);
464 previewData
[i
] = max4f(std::fabs(tmp
[0]),
470 previewData
[i
] = max4f(std::fabs(tmp
[0]),
474 previewData
[i
] = std::max(previewData
[i
], max4f(std::fabs(tmp
[1]),
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]));
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])));
509 const CarlaMutexLocker
cml(fReaderMutex
);
511 const uint channels
= fFileNfo
.channels
;
513 if (channels
== 0 || fFilePtr
== nullptr)
515 carla_debug("R: no song loaded");
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
);
540 float buffer
[kFileReaderBufferSize
];
541 float rbuffer
[kFileReaderBufferSize
];
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)
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
));
566 carla_stderr("R: ad_read failed");
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
);
589 CARLA_SAFE_ASSERT_UINT(fResampler
.inp_count
== 0, fResampler
.inp_count
);
594 CARLA_SAFE_ASSERT(fResampler
.inp_count
== 0);
597 prev_inp_count
= fResampler
.inp_count
;
605 fRingBufferL
.writeCustomData(rbuffer
, r
* sizeof(float));
606 fRingBufferR
.writeCustomData(rbuffer
, r
* sizeof(float));
609 for (ssize_t i
=0; i
< r
;)
611 fRingBufferL
.writeCustomData(&rbuffer
[i
++], sizeof(float));
612 fRingBufferR
.writeCustomData(&rbuffer
[i
++], sizeof(float));
616 if (fQuadMode
== kQuadAll
)
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));
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));
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
);
651 float buffer
[kFileReaderBufferSize
];
654 while (fRingBufferR
.getWritableDataSize() >= sizeof(buffer
))
656 r
= ad_read(fFilePtr
, buffer
, sizeof(buffer
)/sizeof(float));
660 carla_stderr("R: ad_read failed");
670 fRingBufferL
.writeCustomData(buffer
, r
* sizeof(float));
671 fRingBufferR
.writeCustomData(buffer
, r
* sizeof(float));
674 for (ssize_t i
=0; i
< r
;)
676 fRingBufferL
.writeCustomData(&buffer
[i
++], sizeof(float));
677 fRingBufferR
.writeCustomData(&buffer
[i
++], sizeof(float));
681 if (fQuadMode
== kQuadAll
)
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));
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));
702 fRingBufferL
.commitWrite();
703 fRingBufferR
.commitWrite();
707 if (nextFileReadPos
!= -1)
708 fNextFileReadPos
= -1;
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;
732 } fPreviousResampledBuffer
;
734 CarlaHeapRingBuffer fRingBufferL
, fRingBufferR
;
735 uint64_t fRingBufferFramePos
= 0;
737 // assumes reader lock is active
740 fEntireFileLoaded
= false;
742 fLastPlayPosition
= 0.f
;
743 fNextFileReadPos
= -1;
744 fTotalResampledFrames
= 0;
746 fRingBufferFramePos
= 0;
747 fResampleRatio
= 1.0;
750 fInitialMemoryPool
.destroy();
751 fRingBufferL
.deleteBuffer();
752 fRingBufferR
.deleteBuffer();
754 if (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
),
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
;
799 resampledBuffer
= fileBuffer
;
803 // lock, and put data asap
804 const CarlaMutexLocker
cml(fInitialMemoryPool
.mutex
);
809 for (ssize_t i
=0; i
< rv
; ++i
)
810 fInitialMemoryPool
.buffer
[0][i
] = fInitialMemoryPool
.buffer
[1][i
] = resampledBuffer
[i
];
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
++];
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];
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];
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