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