1 /*
2 Audio File Library
3 Copyright (C) 1998-2000, Michael Pruett <michael@68k.org>
4 Copyright (C) 2000, Silicon Graphics, Inc.
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301 USA
20 */
21
22 /*
23 Loop.cpp
24
25 All routines that operate on loops.
26 */
27
28 #include "config.h"
29
30 #include "FileHandle.h"
31 #include "Instrument.h"
32 #include "Setup.h"
33 #include "afinternal.h"
34 #include "audiofile.h"
35 #include "util.h"
36
afInitLoopIDs(AFfilesetup setup,int instid,const int * loopids,int nloops)37 void afInitLoopIDs (AFfilesetup setup, int instid, const int *loopids, int nloops)
38 {
39 if (!_af_filesetup_ok(setup))
40 return;
41
42 if (!_af_unique_ids(loopids, nloops, "loop", AF_BAD_LOOPID))
43 return;
44
45 InstrumentSetup *instrument = setup->getInstrument(instid);
46 if (!instrument)
47 return;
48
49 instrument->freeLoops();
50 if (!instrument->allocateLoops(nloops))
51 return;
52
53 for (int i=0; i < nloops; i++)
54 instrument->loops[i].id = loopids[i];
55 }
56
afGetLoopIDs(AFfilehandle file,int instid,int * loopids)57 int afGetLoopIDs (AFfilehandle file, int instid, int *loopids)
58 {
59 if (!_af_filehandle_ok(file))
60 return AF_FAIL;
61
62 Instrument *instrument = file->getInstrument(instid);
63 if (!instrument)
64 return AF_FAIL;
65
66 if (loopids)
67 for (int i=0; i < instrument->loopCount; i++)
68 loopids[i] = instrument->loops[i].id;
69
70 return instrument->loopCount;
71 }
72
73 /*
74 getLoop returns pointer to requested loop if it exists, and if
75 mustWrite is true, only if handle is writable.
76 */
77
getLoop(AFfilehandle handle,int instid,int loopid,bool mustWrite)78 static Loop *getLoop (AFfilehandle handle, int instid, int loopid,
79 bool mustWrite)
80 {
81 if (!_af_filehandle_ok(handle))
82 return NULL;
83
84 if (mustWrite && !handle->checkCanWrite())
85 return NULL;
86
87 Instrument *instrument = handle->getInstrument(instid);
88 if (!instrument)
89 return NULL;
90
91 return instrument->getLoop(loopid);
92 }
93
94 /*
95 Set loop mode (as in AF_LOOP_MODE_...).
96 */
afSetLoopMode(AFfilehandle file,int instid,int loopid,int mode)97 void afSetLoopMode (AFfilehandle file, int instid, int loopid, int mode)
98 {
99 Loop *loop = getLoop(file, instid, loopid, true);
100
101 if (!loop)
102 return;
103
104 if (mode != AF_LOOP_MODE_NOLOOP &&
105 mode != AF_LOOP_MODE_FORW &&
106 mode != AF_LOOP_MODE_FORWBAKW)
107 {
108 _af_error(AF_BAD_LOOPMODE, "unrecognized loop mode %d", mode);
109 return;
110 }
111
112 loop->mode = mode;
113 }
114
115 /*
116 Get loop mode (as in AF_LOOP_MODE_...).
117 */
afGetLoopMode(AFfilehandle file,int instid,int loopid)118 int afGetLoopMode (AFfilehandle file, int instid, int loopid)
119 {
120 Loop *loop = getLoop(file, instid, loopid, false);
121
122 if (!loop)
123 return -1;
124
125 return loop->mode;
126 }
127
128 /*
129 Set loop count.
130 */
afSetLoopCount(AFfilehandle file,int instid,int loopid,int count)131 int afSetLoopCount (AFfilehandle file, int instid, int loopid, int count)
132 {
133 Loop *loop = getLoop(file, instid, loopid, true);
134
135 if (!loop)
136 return AF_FAIL;
137
138 if (count < 1)
139 {
140 _af_error(AF_BAD_LOOPCOUNT, "invalid loop count: %d", count);
141 return AF_FAIL;
142 }
143
144 loop->count = count;
145 return AF_SUCCEED;
146 }
147
148 /*
149 Get loop count.
150 */
afGetLoopCount(AFfilehandle file,int instid,int loopid)151 int afGetLoopCount(AFfilehandle file, int instid, int loopid)
152 {
153 Loop *loop = getLoop(file, instid, loopid, false);
154
155 if (!loop)
156 return -1;
157
158 return loop->count;
159 }
160
161 /*
162 Set loop start marker id in the file structure
163 */
afSetLoopStart(AFfilehandle file,int instid,int loopid,int markid)164 void afSetLoopStart(AFfilehandle file, int instid, int loopid, int markid)
165 {
166 Loop *loop = getLoop(file, instid, loopid, true);
167
168 if (!loop)
169 return;
170
171 loop->beginMarker = markid;
172 }
173
174 /*
175 Get loop start marker id.
176 */
afGetLoopStart(AFfilehandle file,int instid,int loopid)177 int afGetLoopStart (AFfilehandle file, int instid, int loopid)
178 {
179 Loop *loop = getLoop(file, instid, loopid, false);
180
181 if (!loop)
182 return -1;
183
184 return loop->beginMarker;
185 }
186
187 /*
188 Set loop start frame in the file structure.
189 */
afSetLoopStartFrame(AFfilehandle file,int instid,int loopid,AFframecount startFrame)190 int afSetLoopStartFrame (AFfilehandle file, int instid, int loopid, AFframecount startFrame)
191 {
192 Loop *loop = getLoop(file, instid, loopid, true);
193
194 if (!loop)
195 return -1;
196
197 if (startFrame < 0)
198 {
199 _af_error(AF_BAD_FRAME, "loop start frame must not be negative");
200 return AF_FAIL;
201 }
202
203 int trackid = loop->trackid;
204 int beginMarker = loop->beginMarker;
205
206 afSetMarkPosition(file, trackid, beginMarker, startFrame);
207 return AF_SUCCEED;
208 }
209
210 /*
211 Get loop start frame.
212 */
afGetLoopStartFrame(AFfilehandle file,int instid,int loopid)213 AFframecount afGetLoopStartFrame (AFfilehandle file, int instid, int loopid)
214 {
215 Loop *loop = getLoop(file, instid, loopid, false);
216 if (!loop)
217 return -1;
218
219 int trackid = loop->trackid;
220 int beginMarker = loop->beginMarker;
221
222 return afGetMarkPosition(file, trackid, beginMarker);
223 }
224
225 /*
226 Set loop track id.
227 */
afSetLoopTrack(AFfilehandle file,int instid,int loopid,int track)228 void afSetLoopTrack (AFfilehandle file, int instid, int loopid, int track)
229 {
230 Loop *loop = getLoop(file, instid, loopid, true);
231
232 if (!loop) return;
233
234 loop->trackid = track;
235 }
236
237 /*
238 Get loop track.
239 */
afGetLoopTrack(AFfilehandle file,int instid,int loopid)240 int afGetLoopTrack (AFfilehandle file, int instid, int loopid)
241 {
242 Loop *loop = getLoop(file, instid, loopid, false);
243
244 if (!loop)
245 return -1;
246
247 return loop->trackid;
248 }
249
250 /*
251 Set loop end frame marker id.
252 */
afSetLoopEnd(AFfilehandle file,int instid,int loopid,int markid)253 void afSetLoopEnd (AFfilehandle file, int instid, int loopid, int markid)
254 {
255 Loop *loop = getLoop(file, instid, loopid, true);
256
257 if (!loop)
258 return;
259
260 loop->endMarker = markid;
261 }
262
263 /*
264 Get loop end frame marker id.
265 */
afGetLoopEnd(AFfilehandle file,int instid,int loopid)266 int afGetLoopEnd (AFfilehandle file, int instid, int loopid)
267 {
268 Loop *loop = getLoop(file, instid, loopid, false);
269
270 if (!loop)
271 return -1;
272
273 return loop->endMarker;
274 }
275
276 /*
277 Set loop end frame.
278 */
afSetLoopEndFrame(AFfilehandle file,int instid,int loopid,AFframecount endFrame)279 int afSetLoopEndFrame (AFfilehandle file, int instid, int loopid, AFframecount endFrame)
280 {
281 Loop *loop = getLoop(file, instid, loopid, true);
282 if (!loop)
283 return -1;
284
285 if (endFrame < 0)
286 {
287 _af_error(AF_BAD_FRAME, "loop end frame must not be negative");
288 return AF_FAIL;
289 }
290
291 int trackid = loop->trackid;
292 int endMarker = loop->endMarker;
293
294 afSetMarkPosition(file, trackid, endMarker, endFrame);
295 return AF_SUCCEED;
296 }
297
298 /*
299 Get loop end frame.
300 */
301
afGetLoopEndFrame(AFfilehandle file,int instid,int loopid)302 AFframecount afGetLoopEndFrame (AFfilehandle file, int instid, int loopid)
303 {
304 Loop *loop = getLoop(file, instid, loopid, false);
305
306 if (!loop)
307 return -1;
308
309 int trackid = loop->trackid;
310 int endMarker = loop->endMarker;
311
312 return afGetMarkPosition(file, trackid, endMarker);
313 }
314