1
/*******************************************/
4
by Gary P. Scavone, 2000
6
This object inherits from WvIn and is
7
used to open Audio Interchange File
8
Format files with 16-bit data (signed
11
.aif files are always bif-endian.
13
/*******************************************/
17
#ifdef __LITTLE_ENDIAN__
21
AifWvIn :: AifWvIn(char *fileName, const char *mode)
26
if ( strcmp(mode,"oneshot") && strcmp(mode,"looping") ) {
27
sprintf(msg, "AifWvIn: constructor parameter 'mode' must be oneshot or looping only.\n");
28
throw StkError(msg, StkError::FUNCTION_SYNTAX);
31
// Open the file and get header info
32
fd = fopen(fileName,"rb");
34
sprintf(msg, "AifWvIn: Couldn't open or find file (%s).\n", fileName);
35
throw StkError(msg, StkError::FILE_NOT_FOUND);
38
// Make sure this is an .aif format file
40
fseek(fd,8,SEEK_SET); // Locate form type
42
if (strncmp(id,"AIFF",4)) {
44
sprintf(msg, "AifWvIn: %s doesn't appear to be an AIFF file.\n", fileName);
45
throw StkError(msg, StkError::FILE_ERROR);
48
// Find "common" chunk
51
while (strncmp(id,"COMM",4)) {
52
fread(&chunkSize,4,1,fd);
53
#ifdef __LITTLE_ENDIAN__
54
swap32((unsigned char *)&chunkSize);
56
fseek(fd,chunkSize,SEEK_CUR);
60
// Get number of channels from the header
62
fseek(fd,4,SEEK_CUR); // Jump over chunk size
64
#ifdef __LITTLE_ENDIAN__
65
swap16((unsigned char *)&temp);
69
// Get length of data from the header
71
fread(&frames,4,1,fd);
72
#ifdef __LITTLE_ENDIAN__
73
swap32((unsigned char *)&frames);
75
// length is the number of sample frames
77
bufferSize = fileSize;
79
// Verify that the data is 16 bits per sample
81
#ifdef __LITTLE_ENDIAN__
82
swap16((unsigned char *)&temp);
86
sprintf(msg, "AifWvIn: STK does not currently support data formats other than 16 bit signed integer.\n");
87
throw StkError(msg, StkError::FILE_ERROR);
90
/* Get file sample rate from the header and set the default rate.
91
* For AIFF files, this value is stored in a 10-byte, IEEE Standard
92
* 754 floating point number, so we need to convert it first.
94
unsigned char srate[10];
96
unsigned long mantissa;
97
unsigned long last = 0;;
98
fread(&srate,10,1,fd);
99
mantissa = (unsigned long) *(unsigned long *)(srate+2);
100
#ifdef __LITTLE_ENDIAN__
101
swap32((unsigned char *)&mantissa);
103
exp = 30 - *(srate+1);
108
if (last & 0x00000001) mantissa++;
109
rate = (MY_FLOAT) (mantissa/SRATE); // set default rate based on file sampling rate
113
while (strncmp(id,"SSND",4)) {
114
fread(&chunkSize,4,1,fd);
115
#ifdef __LITTLE_ENDIAN__
116
swap32((unsigned char *)&chunkSize);
118
fseek(fd,chunkSize,SEEK_CUR);
122
// Skip over chunk size, offset, and blocksize fields
123
fseek(fd,12,SEEK_CUR);
125
if ((fileSize*channels) > MAX_FILE_LOAD_SIZE) {
126
printf("\nAifWvIn: The .AIF file (%s) has more than %d samples and\n",
127
fileName, MAX_FILE_LOAD_SIZE);
128
printf("will be loaded incrementally from disk. Normalization will be disabled.\n");
130
bufferSize = LOAD_BUFFER_SIZE;
133
// Setup for looping or one-shot playback
134
if (!strcmp(mode,"looping"))
136
else // default = oneshot
139
data = (MY_FLOAT *) new MY_FLOAT[(bufferSize+1)*channels];
140
dataOffset = ftell(fd);
141
this->getData(0); // Read samples into data[]
143
if (fmod(rate, 1.0) != 0.0) interpolate = 1;
144
else interpolate = 0;
145
phaseOffset = (MY_FLOAT) 0.0;
146
lastOutput = (MY_FLOAT *) new MY_FLOAT[channels];
149
// finally, let's normalize the data by default
153
AifWvIn :: ~AifWvIn()
157
void AifWvIn :: getData(long index)
159
/* Compare index to current readPointer and modify as needed.
160
* The following while() loops will only execute on calls subsequent
161
* to class instantiation ... and thus, only when "chunking".
163
while (index < readPointer) {
164
readPointer -= LOAD_BUFFER_SIZE;
165
bufferSize = LOAD_BUFFER_SIZE;
166
if (readPointer < 0) {
167
bufferSize += readPointer;
171
while (index >= readPointer+bufferSize) {
172
readPointer += LOAD_BUFFER_SIZE;
173
bufferSize = LOAD_BUFFER_SIZE;
174
if (readPointer+LOAD_BUFFER_SIZE >= fileSize) {
175
bufferSize = fileSize - readPointer;
179
fseek(fd, dataOffset+(long)(readPointer*channels*2), SEEK_SET);
180
long length = bufferSize;
181
int end_of_file = (readPointer+bufferSize == fileSize);
182
if (!end_of_file) length += 1;
184
// Read samples into data[]. Use MY _FLOAT data structure to store INT16 samples
185
INT16 *buf = (INT16 *)data;
186
fread(buf, 2, length*channels, fd);
187
// Convert in place (unpack) to MY_FLOAT from the end of the array
188
for (int i=length*channels-1; i>=0; i--) {
189
#ifdef __LITTLE_ENDIAN__
190
swap16((unsigned char *)(buf+i));
193
if (chunking) data[i] *= 0.00003051;
196
// fill in the extra sample frame for interpolation
198
for (int j=0; j<channels; j++)
200
data[bufferSize*channels+j] = data[j];
202
data[bufferSize*channels+j] = data[(bufferSize-1)*channels+j];