(Metux) autogen.sh: not running ./configure anymore (breaks certain distro builders)
[mirror-ossqm-audiofile.git] / libaudiofile / aiff.c
blob03b1d23e24418e48d7c44619be779d9ac822298b
1 /*
2 Audio File Library
3 Copyright (C) 1998-2000, 2003, Michael Pruett <michael@68k.org>
4 Copyright (C) 2000, Silicon Graphics, Inc.
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
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 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with this library; if not, write to the
18 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307 USA.
23 aiff.c
25 This file contains routines for parsing AIFF and AIFF-C sound
26 files.
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
33 #include <assert.h>
34 #include <stdint.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
39 #include "extended.h"
40 #include "audiofile.h"
41 #include "util.h"
42 #include "afinternal.h"
43 #include "byteorder.h"
44 #include "aiff.h"
45 #include "setup.h"
46 #include "track.h"
47 #include "marker.h"
49 static status ParseFVER (AFfilehandle file, AFvirtualfile *fh, uint32_t type,
50 size_t size);
51 static status ParseAESD (AFfilehandle file, AFvirtualfile *fh, uint32_t type,
52 size_t size);
53 static status ParseMiscellaneous (AFfilehandle file, AFvirtualfile *fh,
54 uint32_t type, size_t size);
55 static status ParseINST (AFfilehandle file, AFvirtualfile *fh, uint32_t type,
56 size_t size);
57 static status ParseMARK (AFfilehandle file, AFvirtualfile *fh, uint32_t type,
58 size_t size);
59 static status ParseCOMM (AFfilehandle file, AFvirtualfile *fh, uint32_t type,
60 size_t size);
61 static status ParseSSND (AFfilehandle file, AFvirtualfile *fh, uint32_t type,
62 size_t size);
64 const _InstParamInfo _af_aiff_inst_params[_AF_AIFF_NUM_INSTPARAMS] =
66 { AF_INST_MIDI_BASENOTE, AU_PVTYPE_LONG, "MIDI base note", {60} },
67 { AF_INST_NUMCENTS_DETUNE, AU_PVTYPE_LONG, "Detune in cents", {0} },
68 { AF_INST_MIDI_LOVELOCITY, AU_PVTYPE_LONG, "Low velocity", {1} },
69 { AF_INST_MIDI_HIVELOCITY, AU_PVTYPE_LONG, "High velocity", {127} },
70 { AF_INST_MIDI_LONOTE, AU_PVTYPE_LONG, "Low note", {0} },
71 { AF_INST_MIDI_HINOTE, AU_PVTYPE_LONG, "High note", {127} },
72 { AF_INST_NUMDBS_GAIN, AU_PVTYPE_LONG, "Gain in dB", {0} },
73 { AF_INST_SUSLOOPID, AU_PVTYPE_LONG, "Sustain loop id", {0} },
74 { AF_INST_RELLOOPID, AU_PVTYPE_LONG, "Release loop id", {0} }
77 const int _af_aiffc_compression_types[_AF_AIFF_NUM_COMPTYPES] =
79 AF_COMPRESSION_G711_ULAW,
80 AF_COMPRESSION_G711_ALAW
83 _AFfilesetup _af_aiff_default_filesetup =
85 _AF_VALID_FILESETUP, /* valid */
86 AF_FILE_AIFF, /* fileFormat */
87 true, /* trackSet */
88 true, /* instrumentSet */
89 true, /* miscellaneousSet */
90 1, /* trackCount */
91 NULL, /* tracks */
92 1, /* instrumentCount */
93 NULL, /* instruments */
94 0, /* miscellaneousCount */
95 NULL /* miscellaneous */
99 FVER chunks are only present in AIFF-C files.
101 static status ParseFVER (AFfilehandle file, AFvirtualfile *fh, uint32_t type, size_t size)
103 uint32_t timestamp;
105 assert(!memcmp(&type, "FVER", 4));
107 af_read_uint32_be(&timestamp, fh);
108 /* timestamp holds the number of seconds since January 1, 1904. */
110 return AF_SUCCEED;
114 Parse AES recording data.
116 static status ParseAESD (AFfilehandle file, AFvirtualfile *fh, uint32_t type, size_t size)
118 _Track *track;
119 unsigned char aesChannelStatusData[24];
121 assert(!memcmp(&type, "AESD", 4));
122 assert(size == 24);
124 track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK);
126 track->hasAESData = true;
129 Try to read 24 bytes of AES nonaudio data from the file.
130 Fail if the file disappoints.
132 if (af_fread(aesChannelStatusData, 1, 24, fh) != 24)
133 return AF_FAIL;
135 memcpy(track->aesData, aesChannelStatusData, 24);
137 return AF_SUCCEED;
141 Parse miscellaneous data chunks such as name, author, copyright,
142 and annotation chunks.
144 static status ParseMiscellaneous (AFfilehandle file, AFvirtualfile *fh,
145 uint32_t type, size_t size)
147 int misctype = AF_MISC_UNRECOGNIZED;
149 assert(!memcmp(&type, "NAME", 4) || !memcmp(&type, "AUTH", 4) ||
150 !memcmp(&type, "(c) ", 4) || !memcmp(&type, "ANNO", 4) ||
151 !memcmp(&type, "APPL", 4) || !memcmp(&type, "MIDI", 4));
153 /* Skip zero-length miscellaneous chunks. */
154 if (size == 0)
155 return AF_FAIL;
157 file->miscellaneousCount++;
158 file->miscellaneous = _af_realloc(file->miscellaneous,
159 file->miscellaneousCount * sizeof (_Miscellaneous));
161 if (!memcmp(&type, "NAME", 4))
162 misctype = AF_MISC_NAME;
163 else if (!memcmp(&type, "AUTH", 4))
164 misctype = AF_MISC_AUTH;
165 else if (!memcmp(&type, "(c) ", 4))
166 misctype = AF_MISC_COPY;
167 else if (!memcmp(&type, "ANNO", 4))
168 misctype = AF_MISC_ANNO;
169 else if (!memcmp(&type, "APPL", 4))
170 misctype = AF_MISC_APPL;
171 else if (!memcmp(&type, "MIDI", 4))
172 misctype = AF_MISC_MIDI;
174 file->miscellaneous[file->miscellaneousCount - 1].id = file->miscellaneousCount;
175 file->miscellaneous[file->miscellaneousCount - 1].type = misctype;
176 file->miscellaneous[file->miscellaneousCount - 1].size = size;
177 file->miscellaneous[file->miscellaneousCount - 1].position = 0;
178 file->miscellaneous[file->miscellaneousCount - 1].buffer = _af_malloc(size);
179 af_fread(file->miscellaneous[file->miscellaneousCount - 1].buffer,
180 size, 1, file->fh);
182 return AF_SUCCEED;
186 Parse instrument chunks, which contain information about using
187 sound data as a sampled instrument.
189 static status ParseINST (AFfilehandle file, AFvirtualfile *fh, uint32_t type,
190 size_t size)
192 _Instrument *instrument;
193 uint8_t baseNote;
194 int8_t detune;
195 uint8_t lowNote, highNote, lowVelocity, highVelocity;
196 int16_t gain;
198 uint16_t sustainLoopPlayMode, sustainLoopBegin, sustainLoopEnd;
199 uint16_t releaseLoopPlayMode, releaseLoopBegin, releaseLoopEnd;
201 assert(!memcmp(&type, "INST", 4));
203 instrument = _af_calloc(1, sizeof (_Instrument));
204 instrument->id = AF_DEFAULT_INST;
205 instrument->values = _af_calloc(_AF_AIFF_NUM_INSTPARAMS, sizeof (AFPVu));
206 instrument->loopCount = 2;
207 instrument->loops = _af_calloc(2, sizeof (_Loop));
209 file->instrumentCount = 1;
210 file->instruments = instrument;
212 af_read_uint8(&baseNote, fh);
213 af_read_uint8(&detune, fh);
214 af_read_uint8(&lowNote, fh);
215 af_read_uint8(&highNote, fh);
216 af_read_uint8(&lowVelocity, fh);
217 af_read_uint8(&highVelocity, fh);
218 af_read_uint16_be(&gain, fh);
220 #ifdef DEBUG
221 printf("baseNote/detune/lowNote/highNote/lowVelocity/highVelocity/gain:"
222 " %d %d %d %d %d %d %d\n",
223 baseNote, detune, lowNote, highNote, lowVelocity, highVelocity,
224 gain);
225 #endif
227 instrument->values[0].l = baseNote;
228 instrument->values[1].l = detune;
229 instrument->values[2].l = lowVelocity;
230 instrument->values[3].l = highVelocity;
231 instrument->values[4].l = lowNote;
232 instrument->values[5].l = highNote;
233 instrument->values[6].l = gain;
235 instrument->values[7].l = 1; /* sustain loop id */
236 instrument->values[8].l = 2; /* release loop id */
238 af_read_uint16_be(&sustainLoopPlayMode, fh);
239 af_read_uint16_be(&sustainLoopBegin, fh);
240 af_read_uint16_be(&sustainLoopEnd, fh);
242 af_read_uint16_be(&releaseLoopPlayMode, fh);
243 af_read_uint16_be(&releaseLoopBegin, fh);
244 af_read_uint16_be(&releaseLoopEnd, fh);
246 #ifdef DEBUG
247 printf("sustain loop: mode %d, begin %d, end %d\n",
248 sustainLoopPlayMode, sustainLoopBegin, sustainLoopEnd);
250 printf("release loop: mode %d, begin %d, end %d\n",
251 releaseLoopPlayMode, releaseLoopBegin, releaseLoopEnd);
252 #endif
254 instrument->loops[0].id = 1;
255 instrument->loops[0].mode = sustainLoopPlayMode;
256 instrument->loops[0].beginMarker = sustainLoopBegin;
257 instrument->loops[0].endMarker = sustainLoopEnd;
259 instrument->loops[1].id = 2;
260 instrument->loops[1].mode = releaseLoopPlayMode;
261 instrument->loops[1].beginMarker = releaseLoopBegin;
262 instrument->loops[1].endMarker = releaseLoopEnd;
264 return AF_SUCCEED;
268 Parse marker chunks, which contain the positions and names of loop markers.
270 static status ParseMARK (AFfilehandle file, AFvirtualfile *fh, uint32_t type,
271 size_t size)
273 _Track *track;
274 int i;
275 uint16_t numMarkers;
277 assert(!memcmp(&type, "MARK", 4));
279 track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK);
281 af_read_uint16_be(&numMarkers, fh);
283 track->markerCount = numMarkers;
284 if (numMarkers)
285 track->markers = _af_marker_new(numMarkers);
287 for (i=0; i<numMarkers; i++)
289 uint16_t markerID = 0;
290 uint32_t markerPosition = 0;
291 uint8_t sizeByte = 0;
292 char *markerName = NULL;
294 af_read_uint16_be(&markerID, fh);
295 af_read_uint32_be(&markerPosition, fh);
296 af_fread(&sizeByte, sizeof (unsigned char), 1, fh);
297 markerName = _af_malloc(sizeByte + 1);
298 af_fread(markerName, sizeof (unsigned char), sizeByte, fh);
300 markerName[sizeByte] = '\0';
302 #ifdef DEBUG
303 printf("marker id: %d, position: %d, name: %s\n",
304 markerID, markerPosition, markerName);
306 printf("size byte: %d\n", sizeByte);
307 #endif
310 If sizeByte is even, then 1+sizeByte (the length
311 of the string) is odd. Skip an extra byte to
312 make it even.
315 if ((sizeByte % 2) == 0)
316 af_fseek(fh, 1, SEEK_CUR);
318 track->markers[i].id = markerID;
319 track->markers[i].position = markerPosition;
320 track->markers[i].name = markerName;
321 track->markers[i].comment = _af_strdup("");
324 return AF_SUCCEED;
328 Parse common data chunks, which contain information regarding the
329 sampling rate, the number of sample frames, and the number of
330 sound channels.
332 static status ParseCOMM (AFfilehandle file, AFvirtualfile *fh, uint32_t type,
333 size_t size)
335 _Track *track;
336 uint16_t numChannels;
337 uint32_t numSampleFrames;
338 uint16_t sampleSize;
339 unsigned char sampleRate[10];
341 assert(!memcmp(&type, "COMM", 4));
343 track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK);
345 af_read_uint16_be(&numChannels, fh);
346 track->f.channelCount = numChannels;
348 af_read_uint32_be(&numSampleFrames, fh);
349 track->totalfframes = numSampleFrames;
351 af_read_uint16_be(&sampleSize, fh);
352 track->f.sampleWidth = sampleSize;
354 af_fread(sampleRate, 10, 1, fh);
355 track->f.sampleRate = _af_convert_from_ieee_extended(sampleRate);
357 track->f.compressionType = AF_COMPRESSION_NONE;
358 track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP;
359 track->f.byteOrder = AF_BYTEORDER_BIGENDIAN;
361 if (file->fileFormat == AF_FILE_AIFFC)
363 uint8_t compressionID[4];
364 /* Pascal strings are at most 255 bytes long. */
365 char compressionName[256];
367 af_fread(compressionID, 4, 1, fh);
369 /* Read the Pascal-style string containing the name. */
370 af_read_pstring(compressionName, fh);
372 if (!memcmp(compressionID, "NONE", 4) ||
373 !memcmp(compressionID, "twos", 4))
375 track->f.compressionType = AF_COMPRESSION_NONE;
377 else if (!memcmp(compressionID, "in24", 4))
379 track->f.compressionType = AF_COMPRESSION_NONE;
380 track->f.sampleWidth = 24;
382 else if (!memcmp(compressionID, "in32", 4))
384 track->f.compressionType = AF_COMPRESSION_NONE;
385 track->f.sampleWidth = 32;
387 else if (!memcmp(compressionID, "ACE2", 4) ||
388 !memcmp(compressionID, "ACE8", 4) ||
389 !memcmp(compressionID, "MAC3", 4) ||
390 !memcmp(compressionID, "MAC6", 4))
392 _af_error(AF_BAD_NOT_IMPLEMENTED, "AIFF-C format does not support Apple's proprietary %s compression format", compressionName);
393 return AF_FAIL;
395 else if (!memcmp(compressionID, "ulaw", 4) ||
396 !memcmp(compressionID, "ULAW", 4))
398 track->f.compressionType = AF_COMPRESSION_G711_ULAW;
400 else if (!memcmp(compressionID, "alaw", 4) ||
401 !memcmp(compressionID, "ALAW", 4))
403 track->f.compressionType = AF_COMPRESSION_G711_ALAW;
405 else if (!memcmp(compressionID, "fl32", 4) ||
406 !memcmp(compressionID, "FL32", 4))
408 track->f.sampleFormat = AF_SAMPFMT_FLOAT;
409 track->f.sampleWidth = 32;
410 track->f.compressionType = AF_COMPRESSION_NONE;
412 else if (!memcmp(compressionID, "fl64", 4) ||
413 !memcmp(compressionID, "FL64", 4))
415 track->f.sampleFormat = AF_SAMPFMT_DOUBLE;
416 track->f.sampleWidth = 64;
417 track->f.compressionType = AF_COMPRESSION_NONE;
419 else if (!memcmp(compressionID, "sowt", 4))
421 track->f.compressionType = AF_COMPRESSION_NONE;
422 track->f.byteOrder = AF_BYTEORDER_LITTLEENDIAN;
424 else
426 _af_error(AF_BAD_NOT_IMPLEMENTED, "AIFF-C compression type '%c%c%c%c' not currently supported",
427 compressionID[0],
428 compressionID[1],
429 compressionID[2],
430 compressionID[3]);
431 return AF_FAIL;
435 _af_set_sample_format(&track->f, track->f.sampleFormat, track->f.sampleWidth);
437 return AF_SUCCEED;
441 Parse the stored sound chunk, which usually contains little more
442 than the sound data.
444 static status ParseSSND (AFfilehandle file, AFvirtualfile *fh, uint32_t type,
445 size_t size)
447 _Track *track;
448 uint32_t offset, blockSize;
450 assert(!memcmp(&type, "SSND", 4));
452 track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK);
454 af_read_uint32_be(&offset, fh);
455 af_read_uint32_be(&blockSize, fh);
458 This seems like a reasonable way to calculate the number of
459 bytes in an SSND chunk.
461 track->data_size = size - 8 - offset;
463 #ifdef DEBUG
464 printf("offset: %d\n", offset);
465 printf("block size: %d\n", blockSize);
466 #endif
468 track->fpos_first_frame = af_ftell(fh) + offset;
470 #ifdef DEBUG
471 printf("data start: %d\n", track->fpos_first_frame);
472 #endif
474 /* Sound data follows. */
476 return AF_SUCCEED;
479 status _af_aiff_read_init (AFfilesetup setup, AFfilehandle file)
481 uint32_t type, size, formtype;
482 size_t index = 0;
483 bool hasCOMM, hasFVER, hasSSND, hasMARK, hasINST;
484 bool hasAESD, hasNAME, hasAUTH, hasCOPY;
485 _Track *track;
487 hasCOMM = false;
488 hasFVER = false;
489 hasSSND = false;
490 hasMARK = false;
491 hasINST = false;
492 hasAESD = false;
493 hasNAME = false;
494 hasAUTH = false;
495 hasCOPY = false;
497 assert(file != NULL);
498 assert(file->fh != NULL);
500 af_fseek(file->fh, 0, SEEK_SET);
502 af_fread(&type, 4, 1, file->fh);
503 af_read_uint32_be(&size, file->fh);
504 af_fread(&formtype, 4, 1, file->fh);
506 if (memcmp(&type, "FORM", 4) != 0 ||
507 (memcmp(&formtype, "AIFF", 4) && memcmp(&formtype, "AIFC", 4)))
508 return AF_FAIL;
510 #ifdef DEBUG
511 printf("size: %d\n", size);
512 #endif
514 file->instrumentCount = 0;
515 file->instruments = NULL;
516 file->miscellaneousCount = 0;
517 file->miscellaneous = NULL;
519 /* AIFF files have only one track. */
520 track = _af_track_new();
521 file->trackCount = 1;
522 file->tracks = track;
524 /* Include the offset of the form type. */
525 index += 4;
527 while (index < size)
529 uint32_t chunkid = 0, chunksize = 0;
530 status result = AF_SUCCEED;
532 #ifdef DEBUG
533 printf("index: %d\n", index);
534 #endif
535 af_fread(&chunkid, 4, 1, file->fh);
536 af_read_uint32_be(&chunksize, file->fh);
538 #ifdef DEBUG
539 _af_printid(chunkid);
540 printf(" size: %d\n", chunksize);
541 #endif
543 if (!memcmp("COMM", &chunkid, 4))
545 hasCOMM = true;
546 result = ParseCOMM(file, file->fh, chunkid, chunksize);
548 else if (!memcmp("FVER", &chunkid, 4))
550 hasFVER = true;
551 ParseFVER(file, file->fh, chunkid, chunksize);
553 else if (!memcmp("INST", &chunkid, 4))
555 hasINST = true;
556 ParseINST(file, file->fh, chunkid, chunksize);
558 else if (!memcmp("MARK", &chunkid, 4))
560 hasMARK = true;
561 ParseMARK(file, file->fh, chunkid, chunksize);
563 else if (!memcmp("AESD", &chunkid, 4))
565 hasAESD = true;
566 ParseAESD(file, file->fh, chunkid, chunksize);
568 else if (!memcmp("NAME", &chunkid, 4) ||
569 !memcmp("AUTH", &chunkid, 4) ||
570 !memcmp("(c) ", &chunkid, 4) ||
571 !memcmp("ANNO", &chunkid, 4) ||
572 !memcmp("APPL", &chunkid, 4) ||
573 !memcmp("MIDI", &chunkid, 4))
575 ParseMiscellaneous(file, file->fh, chunkid, chunksize);
578 The sound data chunk is required if there are more than
579 zero sample frames.
581 else if (!memcmp("SSND", &chunkid, 4))
583 if (hasSSND)
585 _af_error(AF_BAD_AIFF_SSND, "AIFF file has more than one SSND chunk");
586 return AF_FAIL;
588 hasSSND = true;
589 result = ParseSSND(file, file->fh, chunkid, chunksize);
592 if (result == AF_FAIL)
593 return AF_FAIL;
595 index += chunksize + 8;
597 /* all chunks must be aligned on an even number of bytes */
598 if ((index % 2) != 0)
599 index++;
601 af_fseek(file->fh, index + 8, SEEK_SET);
604 if (!hasCOMM)
606 _af_error(AF_BAD_AIFF_COMM, "bad AIFF COMM chunk");
609 /* The file has been successfully parsed. */
610 return AF_SUCCEED;
613 bool _af_aiff_recognize (AFvirtualfile *fh)
615 uint8_t buffer[8];
617 af_fseek(fh, 0, SEEK_SET);
619 if (af_fread(buffer, 1, 8, fh) != 8 || memcmp(buffer, "FORM", 4) != 0)
620 return false;
621 if (af_fread(buffer, 1, 4, fh) != 4 || memcmp(buffer, "AIFF", 4) != 0)
622 return false;
624 return true;
627 bool _af_aifc_recognize (AFvirtualfile *fh)
629 uint8_t buffer[8];
631 af_fseek(fh, 0, SEEK_SET);
633 if (af_fread(buffer, 1, 8, fh) != 8 || memcmp(buffer, "FORM", 4) != 0)
634 return false;
635 if (af_fread(buffer, 1, 4, fh) != 4 || memcmp(buffer, "AIFC", 4) != 0)
636 return false;
638 return true;
641 AFfilesetup _af_aiff_complete_setup (AFfilesetup setup)
643 _TrackSetup *track;
645 bool isAIFF = setup->fileFormat == AF_FILE_AIFF;
647 if (setup->trackSet && setup->trackCount != 1)
649 _af_error(AF_BAD_NUMTRACKS, "AIFF/AIFF-C file must have 1 track");
650 return AF_NULL_FILESETUP;
653 track = &setup->tracks[0];
655 if (track->sampleFormatSet)
657 if (track->f.sampleFormat == AF_SAMPFMT_UNSIGNED)
659 _af_error(AF_BAD_FILEFMT, "AIFF/AIFF-C format does not support unsigned data");
660 return AF_NULL_FILESETUP;
662 else if (isAIFF && track->f.sampleFormat != AF_SAMPFMT_TWOSCOMP)
664 _af_error(AF_BAD_FILEFMT, "AIFF format supports only two's complement integer data");
665 return AF_NULL_FILESETUP;
668 else
669 _af_set_sample_format(&track->f, AF_SAMPFMT_TWOSCOMP,
670 track->f.sampleWidth);
672 /* Check sample width if writing two's complement. Otherwise ignore. */
673 if (track->f.sampleFormat == AF_SAMPFMT_TWOSCOMP &&
674 (track->f.sampleWidth < 1 || track->f.sampleWidth > 32))
676 _af_error(AF_BAD_WIDTH,
677 "invalid sample width %d for AIFF/AIFF-C file "
678 "(must be 1-32)", track->f.sampleWidth);
679 return AF_NULL_FILESETUP;
682 if (isAIFF && track->f.compressionType != AF_COMPRESSION_NONE)
684 _af_error(AF_BAD_FILESETUP,
685 "AIFF does not support compression; use AIFF-C");
686 return AF_NULL_FILESETUP;
689 /* XXXmpruett handle compression here */
691 if (track->byteOrderSet &&
692 track->f.byteOrder != AF_BYTEORDER_BIGENDIAN &&
693 track->f.sampleWidth > 8)
695 _af_error(AF_BAD_BYTEORDER,
696 "AIFF/AIFF-C format supports only big-endian data");
698 track->f.byteOrder = AF_BYTEORDER_BIGENDIAN;
700 if (setup->instrumentSet)
702 if (setup->instrumentCount != 0 && setup->instrumentCount != 1)
704 _af_error(AF_BAD_NUMINSTS, "AIFF/AIFF-C file must have 0 or 1 instrument chunk");
705 return AF_NULL_FILESETUP;
707 if (setup->instruments != 0 &&
708 setup->instruments[0].loopCount != 2)
710 _af_error(AF_BAD_NUMLOOPS, "AIFF/AIFF-C file with instrument must also have 2 loops");
711 return AF_NULL_FILESETUP;
715 if (setup->miscellaneousSet)
717 int i;
718 for (i=0; i<setup->miscellaneousCount; i++)
720 switch (setup->miscellaneous[i].type)
722 case AF_MISC_COPY:
723 case AF_MISC_AUTH:
724 case AF_MISC_NAME:
725 case AF_MISC_ANNO:
726 case AF_MISC_APPL:
727 case AF_MISC_MIDI:
728 break;
730 default:
731 _af_error(AF_BAD_MISCTYPE, "invalid miscellaneous type %d for AIFF/AIFF-C file", setup->miscellaneous[i].type);
732 return AF_NULL_FILESETUP;
737 return _af_filesetup_copy(setup, &_af_aiff_default_filesetup, true);
740 bool _af_aiff_instparam_valid (AFfilehandle filehandle, AUpvlist list, int i)
742 int param, type, lval;
744 AUpvgetparam(list, i, &param);
745 AUpvgetvaltype(list, i, &type);
746 if (type != AU_PVTYPE_LONG)
747 return false;
749 AUpvgetval(list, i, &lval);
751 switch (param)
753 case AF_INST_MIDI_BASENOTE:
754 return ((lval >= 0) && (lval <= 127));
756 case AF_INST_NUMCENTS_DETUNE:
757 return ((lval >= -50) && (lval <= 50));
759 case AF_INST_MIDI_LOVELOCITY:
760 return ((lval >= 1) && (lval <= 127));
762 case AF_INST_MIDI_HIVELOCITY:
763 return ((lval >= 1) && (lval <= 127));
765 case AF_INST_MIDI_LONOTE:
766 return ((lval >= 0) && (lval <= 127));
768 case AF_INST_MIDI_HINOTE:
769 return ((lval >= 0) && (lval <= 127));
771 case AF_INST_NUMDBS_GAIN:
772 case AF_INST_SUSLOOPID:
773 case AF_INST_RELLOOPID:
774 return true;
776 default:
777 return false;
778 break;
781 return true;
784 int _af_aifc_get_version (AFfilehandle file)
786 return AIFC_VERSION_1;