LMMS
Loading...
Searching...
No Matches
SFZSound.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 "SFZSound.h"
9#include "SFZReader.h"
10#include "SFZRegion.h"
11#include "SFZSample.h"
12
13namespace sfzero
14{
15
16Sound::Sound(const water::File &fileIn) : file_(fileIn) {}
18{
19 int numRegions = regions_.size();
20
21 for (int i = 0; i < numRegions; ++i)
22 {
23 delete regions_[i];
24 regions_.set(i, nullptr);
25 }
26
28 {
29 delete i.getValue();
30 }
31}
32
33bool Sound::appliesToNote(int /*midiNoteNumber*/)
34{
35 // Just say yes; we can't truly know unless we're told the velocity as well.
36 return true;
37}
38
39bool Sound::appliesToChannel(int /*midiChannel*/) { return true; }
40void Sound::addRegion(Region *region) { regions_.add(region); }
42{
43 path = path.replaceCharacter('\\', '/');
44 defaultPath = defaultPath.replaceCharacter('\\', '/');
45 water::File sampleFile;
46 if (defaultPath.isEmpty())
47 {
48 sampleFile = file_.getSiblingFile(path);
49 }
50 else
51 {
52 water::File defaultDir = file_.getSiblingFile(defaultPath);
53 sampleFile = defaultDir.getChildFile(path);
54 }
55 water::String samplePath = sampleFile.getFullPathName();
56 Sample *sample = samples_[samplePath];
57 if (sample == nullptr)
58 {
59 sample = new Sample(sampleFile);
60 samples_.set(samplePath, sample);
61 }
62 return sample;
63}
64
66
68{
69 if (!unsupportedOpcodes_.contains(opcode))
70 {
72 water::String warning = "unsupported opcode: ";
73 warning << opcode;
74 warnings_.add(warning);
75 }
76}
77
79{
80 Reader reader(this);
81
82 reader.read(file_);
83}
84
86{
88 {
89 Sample* const sample = i.getValue();
90
91 if (sample->load())
92 {
93 carla_debug("Loaded sample '%s'", sample->getShortName().toRawUTF8());
94 cb.callback(cb.callbackPtr);
95 }
96 else
97 {
98 addError("Couldn't load sample \"" + sample->getShortName() + "\"");
99 }
100 }
101}
102
103Region *Sound::getRegionFor(int note, int velocity, Region::Trigger trigger)
104{
105 int numRegions = regions_.size();
106
107 for (int i = 0; i < numRegions; ++i)
108 {
109 Region *region = regions_[i];
110 if (region->matches(note, velocity, trigger))
111 {
112 return region;
113 }
114 }
115
116 return nullptr;
117}
118
119int Sound::getNumRegions() { return regions_.size(); }
120
121Region *Sound::regionAt(int index) { return regions_[index]; }
122
124{
126 const water::StringArray& errors = getErrors();
127 if (errors.size() > 0)
128 {
129 info << errors.size() << " errors: \n";
130 info << errors.joinIntoString("\n");
131 info << "\n";
132 }
133 else
134 {
135 info << "no errors.\n\n";
136 }
137
138 const water::StringArray& warnings = getWarnings();
139 if (warnings.size() > 0)
140 {
141 info << warnings.size() << " warnings: \n";
142 info << warnings.joinIntoString("\n");
143 }
144 else
145 {
146 info << "no warnings.\n";
147 }
148
149#ifdef DEBUG
150 if (regions_.size() > 0)
151 {
152 info << regions_.size() << " regions: \n";
153 for (int i = 0; i < regions_.size(); ++i)
154 {
155 info << regions_[i]->dump();
156 }
157 }
158 else
159 {
160 info << "no regions.\n";
161 }
162
163 if (samples_.size() > 0)
164 {
165 info << samples_.size() << " samples: \n";
167 {
168 info << i.getValue()->dump();
169 }
170 }
171 else
172 {
173 info << "no samples.\n";
174 }
175#endif
176
177 return info;
178}
179
181{
182 const water::String filename(file_.getFileNameWithoutExtension());
183
184 const water::StringArray& errors(getErrors());
185 const water::StringArray& warnings(getWarnings());
186
187 const int numErrors = errors.size();
188 const int numWarnings = warnings.size();
189
190 if (numErrors == 0 && numWarnings == 0)
191 {
192 carla_stdout("SFZ '%s' loaded without errors or warnings, nice! :)", filename.toRawUTF8());
193 return;
194 }
195
196 if (numErrors != 0)
197 {
198 carla_stdout("SFZ '%s' loaded with %i errors and %i warnings:", filename.toRawUTF8(), numErrors, numWarnings);
199
200 if (numWarnings != 0)
201 carla_stdout("Errors:");
202
203 carla_stdout("%s", errors.joinIntoString("\n").toRawUTF8());
204
205 if (numWarnings != 0)
206 {
207 carla_stdout("Warnings:");
208 carla_stdout("%s", warnings.joinIntoString("\n").toRawUTF8());
209 }
210 }
211
212 carla_stdout("SFZ '%s' loaded without errors, but has %i warnings:", filename.toRawUTF8(), numWarnings);
213 carla_stdout("%s", warnings.joinIntoString("\n").toRawUTF8());
214}
215
216}
opcode
Definition Spc_Cpu.h:173
static void warning(const char *str,...)
Definition adl.cpp:69
static void message(int level, const char *fmt,...)
Definition adplugdb.cpp:120
Definition SFZReader.h:21
void read(const water::File &file)
Definition SFZReader.cpp:20
Definition SFZSample.h:21
void dumpToConsole()
Definition SFZSound.cpp:180
water::File file_
Definition SFZSound.h:59
Sound(const water::File &file)
Definition SFZSound.cpp:16
water::HashMap< water::String, water::String > unsupportedOpcodes_
Definition SFZSound.h:64
Region * regionAt(int index)
Definition SFZSound.cpp:121
virtual void loadRegions()
Definition SFZSound.cpp:78
int getNumRegions()
Definition SFZSound.cpp:119
water::StringArray errors_
Definition SFZSound.h:62
virtual ~Sound()
Definition SFZSound.cpp:17
const water::StringArray & getErrors()
Definition SFZSound.h:49
const water::StringArray & getWarnings()
Definition SFZSound.h:50
bool appliesToChannel(int midiChannel) override
Definition SFZSound.cpp:39
water::String dump()
Definition SFZSound.cpp:123
Region * getRegionFor(int note, int velocity, Region::Trigger trigger=Region::attack)
Definition SFZSound.cpp:103
Sample * addSample(water::String path, water::String defaultPath=water::String())
Definition SFZSound.cpp:41
water::StringArray warnings_
Definition SFZSound.h:63
void addUnsupportedOpcode(const water::String &opcode)
Definition SFZSound.cpp:67
water::Array< Region * > regions_
Definition SFZSound.h:60
void addRegion(Region *region)
Definition SFZSound.cpp:40
virtual void loadSamples(const LoadingIdleCallback &cb)
Definition SFZSound.cpp:85
water::HashMap< water::String, Sample * > samples_
Definition SFZSound.h:61
void addError(const water::String &message)
Definition SFZSound.cpp:65
bool appliesToNote(int midiNoteNumber) override
Definition SFZSound.cpp:33
Definition File.h:50
File getChildFile(StringRef relativeOrAbsolutePath) const
Definition File.cpp:418
const String & getFullPathName() const noexcept
Definition File.h:152
Definition StringArray.h:41
int size() const noexcept
Definition StringArray.h:97
String joinIntoString(StringRef separatorString, int startIndex=0, int numberOfElements=-1) const
Definition StringArray.cpp:270
Definition String.h:48
const char * toRawUTF8() const
Definition String.cpp:1925
String replaceCharacter(water_uchar characterToReplace, water_uchar characterToInsertInstead) const
Definition String.cpp:1217
bool isEmpty() const noexcept
Definition String.h:238
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
Definition SFZRegion.h:30
bool matches(int note, int velocity, Trigger trig)
Definition SFZRegion.h:58
Trigger
Definition SFZRegion.h:32
Definition SFZSound.h:24
void(* callback)(void *)
Definition SFZSound.h:25
void * callbackPtr
Definition SFZSound.h:26
Definition HashMap.h:359
signed int sample
Definition tap_dynamics_m.c:41