LMMS
Loading...
Searching...
No Matches
SFZSample.cpp
Go to the documentation of this file.
1/*************************************************************************************
2 * Original code copyright (C) 2012 Steve Folta
3 * Converted to Juce module (C) 2016 Leo Olivers
4 * Forked from https://github.com/stevefolta/SFZero
5 * For license info please see the LICENSE file distributed with this source code
6 *************************************************************************************/
7
8#include "SFZSample.h"
9#include "SFZDebug.h"
10
11#if 0
12#include "water/audioformat/AudioFormatManager.h"
13#include "water/audioformat/AudioFormatReader.h"
14#include "water/text/StringPairArray.h"
15#else
16extern "C" {
17#include "audio_decoder/ad.h"
18}
19#endif
20
21namespace sfzero
22{
23
25{
26#if 0
27 static water::AudioFormatManager afm;
28 static bool needsInit = true;
29 if (needsInit)
30 {
31 needsInit = false;
32 afm.registerBasicFormats();
33 }
34
35 water::AudioFormatReader* reader = afm.createReaderFor(file_);
36 CARLA_SAFE_ASSERT_RETURN(reader != nullptr, false);
37
38 sampleRate_ = reader->sampleRate;
39 sampleLength_ = (water::uint64) reader->lengthInSamples;
40
41 // Read some extra samples, which will be filled with zeros, so interpolation
42 // can be done without having to check for the edge all the time.
43 CARLA_SAFE_ASSERT_RETURN(sampleLength_ < std::numeric_limits<int>::max(), false);
44
45 water::AudioSampleBuffer* buf = new water::AudioSampleBuffer((int) reader->numChannels, static_cast<int>(sampleLength_ + 4), true);
46 reader->read(buf, 0, static_cast<int>(sampleLength_ + 4), 0, true, true);
47 buffer_ = buf;
48
49 water::StringPairArray *metadata = &reader->metadataValues;
50 int numLoops = metadata->getValue("NumSampleLoops", "0").getIntValue();
51 if (numLoops > 0)
52 {
53 loopStart_ = (water::uint64) metadata->getValue("Loop0Start", "0").getLargeIntValue();
54 loopEnd_ = (water::uint64) metadata->getValue("Loop0End", "0").getLargeIntValue();
55 }
56 delete reader;
57#else
58 const water::String filename(file_.getFullPathName());
59
60 struct adinfo info;
61 carla_zeroStruct(info);
62
63 void* const handle = ad_open(filename.toRawUTF8(), &info);
64 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, false);
65
66 if (info.frames >= std::numeric_limits<int>::max())
67 {
68 carla_stderr2("sfzero::Sample::load() - file is too big!");
69 ad_close(handle);
70 return false;
71 }
72
73 sampleRate_ = info.sample_rate;
74 sampleLength_ = info.frames/info.channels;
75 // TODO loopStart_, loopEnd_
76
77 // read interleaved buffer
78 float* const rbuffer = (float*)std::calloc(1, sizeof(float)*info.frames);
79
80 if (rbuffer == nullptr)
81 {
82 carla_stderr2("sfzero::Sample::load() - out of memory");
83 ad_close(handle);
84 return false;
85 }
86
87 // Fix for misinformation using libsndfile
88 if (info.frames % info.channels)
89 --info.frames;
90
91 const ssize_t r = ad_read(handle, rbuffer, info.frames);
92 if (r != info.frames)
93 {
94 if (r != 0)
95 carla_stderr2("sfzero::Sample::load() - failed to read complete file: " P_SSIZE " vs " P_INT64, r, info.frames);
96 ad_close(handle);
97 return false;
98 }
99
100 // NOTE: We add some extra samples, which will be filled with zeros,
101 // so interpolation can be done without having to check for the edge all the time.
102
103 buffer_ = new water::AudioSampleBuffer(info.channels, sampleLength_ + 4, true);
104
105 for (int i=info.channels; --i >= 0;)
106 buffer_->copyFromInterleavedSource(i, rbuffer, r);
107
108 std::free(rbuffer);
109 ad_close(handle);
110#endif
111
112 return true;
113}
114
116
117water::String Sample::getShortName() { return (file_.getFileName()); }
118
120{
121 buffer_ = newBuffer;
122 sampleLength_ = buffer_->getNumSamples();
123}
124
126{
127 return buffer_.release();
128}
129
130water::String Sample::dump() { return file_.getFullPathName() + "\n"; }
131
132#ifdef DEBUG
133void Sample::checkIfZeroed(const char *where)
134{
135 if (buffer_ == nullptr)
136 {
137 dbgprintf("SFZSample::checkIfZeroed(%s): no buffer!", where);
138 return;
139 }
140
141 int samplesLeft = buffer_->getNumSamples();
142 water::int64 nonzero = 0, zero = 0;
143 const float *p = buffer_->getReadPointer(0);
144 for (; samplesLeft > 0; --samplesLeft)
145 {
146 if (*p++ == 0.0)
147 {
148 zero += 1;
149 }
150 else
151 {
152 nonzero += 1;
153 }
154 }
155 if (nonzero > 0)
156 {
157 dbgprintf("Buffer not zeroed at %s (%lu vs. %lu).", where, nonzero, zero);
158 }
159 else
160 {
161 dbgprintf("Buffer zeroed at %s! (%lu zeros)", where, zero);
162 }
163}
164#endif // DEBUG
165
166}
#define P_SSIZE
Definition CarlaDefines.h:141
#define CARLA_SAFE_ASSERT_RETURN(cond, ret)
Definition CarlaDefines.h:190
#define P_INT64
Definition CarlaDefines.h:136
audio-decoder - wrapper around libsndfile and libav*
int ad_close(void *sf)
Definition ad_plugin.c:96
ssize_t ad_read(void *sf, float *out, size_t len)
Definition ad_plugin.c:110
void * ad_open(const char *fn, struct adinfo *nfo)
Definition ad_plugin.c:72
water::uint64 loopEnd_
Definition SFZSample.h:47
virtual ~Sample()
Definition SFZSample.cpp:115
water::uint64 loopStart_
Definition SFZSample.h:47
water::String getShortName()
Definition SFZSample.cpp:117
water::AudioSampleBuffer * detachBuffer()
Definition SFZSample.cpp:125
water::String dump()
Definition SFZSample.cpp:130
CarlaScopedPointer< water::AudioSampleBuffer > buffer_
Definition SFZSample.h:45
water::File file_
Definition SFZSample.h:44
bool load()
Definition SFZSample.cpp:24
double sampleRate_
Definition SFZSample.h:46
water::uint64 sampleLength_
Definition SFZSample.h:47
void setBuffer(water::AudioSampleBuffer *newBuffer)
Definition SFZSample.cpp:119
Definition AudioSampleBuffer.h:42
Definition String.h:48
register unsigned i
Definition inflate.c:1575
static char filename[]
Definition features.c:5
struct backing_store_struct * info
Definition jmemsys.h:183
Definition SFZDebug.cpp:11
unsigned long long uint64
Definition water.h:102
long long int64
Definition water.h:100
Definition ad.h:37
uch * p
Definition crypt.c:594
int r
Definition crypt.c:458