ft2-clone

Fasttracker 2 clone
Log | Files | Refs | README | LICENSE

ft2_load_aiff.c (14799B)


      1 /* Apple AIFF sample loader
      2 **
      3 ** Note: Vol/loop sanitation is done in the last stage
      4 ** of sample loading, so you don't need to do that here.
      5 ** Do NOT close the file handle!
      6 */
      7 
      8 #include <stdio.h>
      9 #include <stdint.h>
     10 #include <stdbool.h>
     11 #include <math.h>
     12 #include "../ft2_header.h"
     13 #include "../ft2_audio.h"
     14 #include "../ft2_sample_ed.h"
     15 #include "../ft2_sysreqs.h"
     16 #include "../ft2_sample_loader.h"
     17 
     18 static double getAIFFSampleRate(uint8_t *in);
     19 static bool aiffIsStereo(FILE *f); // only ran on files that are confirmed to be AIFFs
     20 
     21 bool loadAIFF(FILE *f, uint32_t filesize)
     22 {
     23 	char compType[4];
     24 	int8_t *audioDataS8;
     25 	uint8_t sampleRateBytes[10], *audioDataU8;
     26 	int16_t *audioDataS16, smp16;
     27 	uint16_t numChannels, bitDepth;
     28 	int32_t *audioDataS32;
     29 	uint32_t i, blockName, blockSize;
     30 	uint32_t offset, len32;
     31 	sample_t *s = &tmpSmp;
     32 
     33 	fseek(f, 8, SEEK_SET);
     34 	fread(compType, 1, 4, f);
     35 	rewind(f);
     36 
     37 	if (filesize < 12)
     38 	{
     39 		loaderMsgBox("Error loading sample: The sample is not supported or is invalid!");
     40 		return false;
     41 	}
     42 
     43 	uint32_t commPtr = 0, commLen = 0;
     44 	uint32_t ssndPtr = 0, ssndLen = 0;
     45 
     46 	fseek(f, 12, SEEK_SET);
     47 	while (!feof(f) && (uint32_t)ftell(f) < filesize-12)
     48 	{
     49 		fread(&blockName, 4, 1, f); if (feof(f)) break;
     50 		fread(&blockSize, 4, 1, f); if (feof(f)) break;
     51 
     52 		blockName = SWAP32(blockName);
     53 		blockSize = SWAP32(blockSize);
     54 
     55 		switch (blockName)
     56 		{
     57 			case 0x434F4D4D: // "COMM"
     58 			{
     59 				commPtr = ftell(f);
     60 				commLen = blockSize;
     61 			}
     62 			break;
     63 
     64 			case 0x53534E44: // "SSND"
     65 			{
     66 				ssndPtr = ftell(f);
     67 				ssndLen = blockSize;
     68 			}
     69 			break;
     70 
     71 			default: break;
     72 		}
     73 
     74 		fseek(f, blockSize + (blockSize & 1), SEEK_CUR);
     75 	}
     76 
     77 	if (commPtr == 0 || commLen < 18 || ssndPtr == 0)
     78 	{
     79 		loaderMsgBox("Error loading sample: The sample is not supported or is invalid!");
     80 		return false;
     81 	}
     82 
     83 	// kludge for strange AIFFs
     84 	if (ssndLen == 0)
     85 		ssndLen = filesize - ssndPtr;
     86 
     87 	if (ssndPtr+ssndLen > (uint32_t)filesize)
     88 		ssndLen = filesize - ssndPtr;
     89 
     90 	fseek(f, commPtr, SEEK_SET);
     91 	fread(&numChannels, 2, 1, f); numChannels = SWAP16(numChannels);
     92 	fseek(f, 4, SEEK_CUR);
     93 	fread(&bitDepth, 2, 1, f); bitDepth = SWAP16(bitDepth);
     94 	fread(sampleRateBytes, 1, 10, f);
     95 
     96 	if (numChannels != 1 && numChannels != 2)
     97 	{
     98 		loaderMsgBox("Error loading sample: Unsupported amounts of channels!");
     99 		return false;
    100 	}
    101 
    102 	// read compression type (if present)
    103 	bool signedSample = true;
    104 	bool floatSample = false;
    105 	if (commLen > 18)
    106 	{
    107 		fread(&compType, 1, 4, f);
    108 
    109 		if (!memcmp(compType, "raw ", 4))
    110 		{
    111 			signedSample = false;
    112 		}
    113 		else if (!memcmp(compType, "FL32", 4) || !memcmp(compType, "fl32", 4) || !memcmp(compType, "FL64", 4) || !memcmp(compType, "fl64", 4))
    114 		{
    115 			floatSample = true;
    116 		}
    117 		else
    118 		{
    119 			loaderMsgBox("Error loading sample: Unsupported AIFF type!");
    120 			return false;
    121 		}
    122 	}
    123 
    124 	if (bitDepth != 8 && bitDepth != 16 && bitDepth != 24 && bitDepth != 32 &&
    125 		!(floatSample && bitDepth == 64) && !(floatSample && bitDepth == 32))
    126 	{
    127 		loaderMsgBox("Error loading sample: Unsupported AIFF type!");
    128 		return false;
    129 	}
    130 
    131 	double dSampleRate = getAIFFSampleRate(sampleRateBytes);
    132 
    133 	// sample data chunk
    134 
    135 	fseek(f, ssndPtr, SEEK_SET);
    136 
    137 	fread(&offset, 4, 1, f);
    138 	if (offset > 0)
    139 	{
    140 		loaderMsgBox("Error loading sample: The sample is not supported or is invalid!");
    141 		return false;
    142 	}
    143 
    144 	fseek(f, 4, SEEK_CUR);
    145 
    146 	ssndLen -= 8; // don't include offset and blockSize datas
    147 
    148 	uint32_t sampleLength = ssndLen;
    149 
    150 	int16_t stereoSampleLoadMode = -1;
    151 	if (aiffIsStereo(f))
    152 		stereoSampleLoadMode = loaderSysReq(4, "System request", "This is a stereo sample...", NULL);
    153 
    154 	// read sample data
    155 
    156 	if (!floatSample && bitDepth == 8) // 8-BIT INTEGER SAMPLE
    157 	{
    158 		if (!allocateSmpData(s, sampleLength, false))
    159 		{
    160 			loaderMsgBox("Not enough memory!");
    161 			return false;
    162 		}
    163 
    164 		if (fread(s->dataPtr, sampleLength, 1, f) != 1)
    165 		{
    166 			loaderMsgBox("General I/O error during loading! Is the file in use?");
    167 			return false;
    168 		}
    169 
    170 		audioDataS8 = (int8_t *)s->dataPtr;
    171 		if (!signedSample)
    172 		{
    173 			for (i = 0; i < sampleLength; i++)
    174 				audioDataS8[i] ^= 0x80;
    175 		}
    176 
    177 		// stereo conversion
    178 		if (numChannels == 2)
    179 		{
    180 			sampleLength /= 2;
    181 
    182 			switch (stereoSampleLoadMode)
    183 			{
    184 				case STEREO_SAMPLE_READ_LEFT:
    185 				{
    186 					for (i = 1; i < sampleLength; i++)
    187 						audioDataS8[i] = audioDataS8[(i * 2) + 0];
    188 				}
    189 				break;
    190 
    191 				case STEREO_SAMPLE_READ_RIGHT:
    192 				{
    193 					len32 = sampleLength - 1;
    194 					for (i = 0; i < len32; i++)
    195 						audioDataS8[i] = audioDataS8[(i * 2) + 1];
    196 
    197 					audioDataS8[i] = 0;
    198 				}
    199 				break;
    200 
    201 				default:
    202 				case STEREO_SAMPLE_CONVERT:
    203 				{
    204 					len32 = sampleLength - 1;
    205 					for (i = 0; i < len32; i++)
    206 					{
    207 						smp16 = (audioDataS8[(i * 2) + 0] + audioDataS8[(i * 2) + 1]) >> 1;
    208 						audioDataS8[i] = (int8_t)smp16;
    209 					}
    210 
    211 					audioDataS8[i] = 0;
    212 				}
    213 				break;
    214 			}
    215 		}
    216 	}
    217 	else if (!floatSample && bitDepth == 16) // 16-BIT INTEGER SAMPLE
    218 	{
    219 		sampleLength /= sizeof (int16_t);
    220 		if (!allocateSmpData(s, sampleLength * sizeof (int16_t), false))
    221 		{
    222 			loaderMsgBox("Not enough memory!");
    223 			return false;
    224 		}
    225 
    226 		if (fread(s->dataPtr, sampleLength, sizeof (int16_t), f) != sizeof (int16_t))
    227 		{
    228 			loaderMsgBox("General I/O error during loading! Is the file in use?");
    229 			return false;
    230 		}
    231 
    232 		// change endianness
    233 		audioDataS16 = (int16_t *)s->dataPtr;
    234 		for (i = 0; i < sampleLength; i++)
    235 			audioDataS16[i] = SWAP16(audioDataS16[i]);
    236 
    237 		// stereo conversion
    238 		if (numChannels == 2)
    239 		{
    240 			sampleLength /= 2;
    241 
    242 			switch (stereoSampleLoadMode)
    243 			{
    244 				case STEREO_SAMPLE_READ_LEFT:
    245 				{
    246 					for (i = 1; i < sampleLength; i++)
    247 						audioDataS16[i] = audioDataS16[(i * 2) + 0];
    248 				}
    249 				break;
    250 
    251 				case STEREO_SAMPLE_READ_RIGHT:
    252 				{
    253 					len32 = sampleLength - 1;
    254 					for (i = 0; i < len32; i++)
    255 						audioDataS16[i] = audioDataS16[(i * 2) + 1];
    256 
    257 					audioDataS16[i] = 0;
    258 				}
    259 				break;
    260 
    261 				default:
    262 				case STEREO_SAMPLE_CONVERT:
    263 				{
    264 					len32 = sampleLength - 1;
    265 					for (i = 0; i < len32; i++)
    266 					{
    267 						int32_t smp32 = (audioDataS16[(i * 2) + 0] + audioDataS16[(i * 2) + 1]) >> 1;
    268 						audioDataS16[i] = (int16_t)smp32;
    269 					}
    270 
    271 					audioDataS16[i] = 0;
    272 				}
    273 				break;
    274 			}
    275 		}
    276 
    277 		s->flags |= SAMPLE_16BIT;
    278 	}
    279 	else if (!floatSample && bitDepth == 24) // 24-BIT INTEGER SAMPLE
    280 	{
    281 		sampleLength /= 3;
    282 		if (!allocateSmpData(s, sampleLength * sizeof (int32_t), false))
    283 		{
    284 			loaderMsgBox("Not enough memory!");
    285 			return false;
    286 		}
    287 
    288 		if (fread(&s->dataPtr[sampleLength], sampleLength, 3, f) != 3)
    289 		{
    290 			loaderMsgBox("General I/O error during loading! Is the file in use?");
    291 			return false;
    292 		}
    293 
    294 		audioDataS32 = (int32_t *)s->dataPtr;
    295 
    296 		// convert to 32-bit
    297 		audioDataU8 = (uint8_t *)s->dataPtr + sampleLength;
    298 		for (i = 0; i < sampleLength; i++)
    299 		{
    300 			audioDataS32[i] = (audioDataU8[0] << 24) | (audioDataU8[1] << 16) | (audioDataU8[2] << 8);
    301 			audioDataU8 += 3;
    302 		}
    303 
    304 		// stereo conversion
    305 		if (numChannels == 2)
    306 		{
    307 			sampleLength /= 2;
    308 
    309 			switch (stereoSampleLoadMode)
    310 			{
    311 				case STEREO_SAMPLE_READ_LEFT:
    312 				{
    313 					for (i = 1; i < sampleLength; i++)
    314 						audioDataS32[i] = audioDataS32[(i * 2) + 0];
    315 				}
    316 				break;
    317 
    318 				case STEREO_SAMPLE_READ_RIGHT:
    319 				{
    320 					len32 = sampleLength - 1;
    321 					for (i = 0; i < len32; i++)
    322 						audioDataS32[i] = audioDataS32[(i * 2) + 1];
    323 
    324 					audioDataS32[i] = 0;
    325 				}
    326 				break;
    327 
    328 				default:
    329 				case STEREO_SAMPLE_CONVERT:
    330 				{
    331 					len32 = sampleLength - 1;
    332 					for (i = 0; i < len32; i++)
    333 					{
    334 						int64_t smp64 = audioDataS32[(i * 2) + 0];
    335 						smp64 += audioDataS32[(i * 2) + 1];
    336 						smp64 >>= 1;
    337 
    338 						audioDataS32[i] = (int32_t)smp64;
    339 					}
    340 
    341 					audioDataS32[i] = 0;
    342 				}
    343 				break;
    344 			}
    345 		}
    346 
    347 		normalizeSigned32Bit(audioDataS32, sampleLength);
    348 
    349 		audioDataS16 = (int16_t *)s->dataPtr;
    350 		for (i = 0; i < sampleLength; i++)
    351 			audioDataS16[i] = audioDataS32[i] >> 16;
    352 
    353 		s->flags |= SAMPLE_16BIT;
    354 	}
    355 	else if (!floatSample && bitDepth == 32) // 32-BIT INTEGER SAMPLE
    356 	{
    357 		sampleLength /= sizeof (int32_t);
    358 		if (!allocateSmpData(s, sampleLength * sizeof (int32_t), false))
    359 		{
    360 			loaderMsgBox("Not enough memory!");
    361 			return false;
    362 		}
    363 
    364 		if (fread(s->dataPtr, sampleLength, sizeof (int32_t), f) != sizeof (int32_t))
    365 		{
    366 			loaderMsgBox("General I/O error during loading! Is the file in use?");
    367 			return false;
    368 		}
    369 
    370 		// change endianness
    371 		audioDataS32 = (int32_t *)s->dataPtr;
    372 		for (i = 0; i < sampleLength; i++)
    373 			audioDataS32[i] = SWAP32(audioDataS32[i]);
    374 
    375 		// stereo conversion
    376 		if (numChannels == 2)
    377 		{
    378 			sampleLength /= 2;
    379 
    380 			switch (stereoSampleLoadMode)
    381 			{
    382 				case STEREO_SAMPLE_READ_LEFT:
    383 				{
    384 					for (i = 1; i < sampleLength; i++)
    385 						audioDataS32[i] = audioDataS32[(i * 2) + 0];
    386 				}
    387 				break;
    388 
    389 				case STEREO_SAMPLE_READ_RIGHT:
    390 				{
    391 					len32 = sampleLength - 1;
    392 					for (i = 0; i < len32; i++)
    393 						audioDataS32[i] = audioDataS32[(i * 2) + 1];
    394 
    395 					audioDataS32[i] = 0;
    396 				}
    397 				break;
    398 
    399 				default:
    400 				case STEREO_SAMPLE_CONVERT:
    401 				{
    402 					len32 = sampleLength - 1;
    403 					for (i = 0; i < len32; i++)
    404 					{
    405 						int64_t smp64 = audioDataS32[(i * 2) + 0];
    406 						smp64 += audioDataS32[(i * 2) + 1];
    407 						smp64 >>= 1;
    408 
    409 						audioDataS32[i] = (int32_t)smp64;
    410 					}
    411 
    412 					audioDataS32[i] = 0;
    413 				}
    414 				break;
    415 			}
    416 		}
    417 
    418 		normalizeSigned32Bit(audioDataS32, sampleLength);
    419 
    420 		audioDataS16 = (int16_t *)s->dataPtr;
    421 		for (i = 0; i < sampleLength; i++)
    422 			audioDataS16[i] = audioDataS32[i] >> 16;
    423 
    424 		s->flags |= SAMPLE_16BIT;
    425 	}
    426 	else if (floatSample && bitDepth == 32) // 32-BIT FLOAT SAMPLE
    427 	{
    428 		sampleLength /= sizeof (float);
    429 		if (!allocateSmpData(s, sampleLength * sizeof (float), false))
    430 		{
    431 			loaderMsgBox("Not enough memory!");
    432 			return false;
    433 		}
    434 
    435 		if (fread(s->dataPtr, sampleLength, sizeof (float), f) != sizeof (float))
    436 		{
    437 			loaderMsgBox("General I/O error during loading! Is the file in use?");
    438 			return false;
    439 		}
    440 
    441 		// change endianness
    442 		audioDataS32 = (int32_t *)s->dataPtr;
    443 		for (i = 0; i < sampleLength; i++)
    444 			audioDataS32[i] = SWAP32(audioDataS32[i]);
    445 
    446 		float *fAudioDataFloat = (float *)s->dataPtr;
    447 
    448 		// stereo conversion
    449 		if (numChannels == 2)
    450 		{
    451 			sampleLength /= 2;
    452 			switch (stereoSampleLoadMode)
    453 			{
    454 				case STEREO_SAMPLE_READ_LEFT:
    455 				{
    456 					// remove right channel data
    457 					for (i = 1; i < sampleLength; i++)
    458 						fAudioDataFloat[i] = fAudioDataFloat[(i * 2) + 0];
    459 				}
    460 				break;
    461 
    462 				case STEREO_SAMPLE_READ_RIGHT:
    463 				{
    464 					// remove left channel data
    465 					len32 = sampleLength - 1;
    466 					for (i = 0; i < len32; i++)
    467 						fAudioDataFloat[i] = fAudioDataFloat[(i * 2) + 1];
    468 
    469 					fAudioDataFloat[i] = 0.0f;
    470 				}
    471 				break;
    472 
    473 				default:
    474 				case STEREO_SAMPLE_CONVERT:
    475 				{
    476 					// mix stereo to mono
    477 					len32 = sampleLength - 1;
    478 					for (i = 0; i < len32; i++)
    479 						fAudioDataFloat[i] = (fAudioDataFloat[(i * 2) + 0] + fAudioDataFloat[(i * 2) + 1]) * 0.5f;
    480 
    481 					fAudioDataFloat[i] = 0.0f;
    482 				}
    483 				break;
    484 			}
    485 		}
    486 
    487 		normalize32BitFloatToSigned16Bit(fAudioDataFloat, sampleLength);
    488 
    489 		int16_t *ptr16 = (int16_t *)s->dataPtr;
    490 		for (i = 0; i < sampleLength; i++)
    491 		{
    492 			const int32_t smp32 = (const int32_t)fAudioDataFloat[i];
    493 			ptr16[i] = (int16_t)smp32;
    494 		}
    495 
    496 		s->flags |= SAMPLE_16BIT;
    497 	}
    498 	else if (floatSample && bitDepth == 64) // 64-BIT FLOAT SAMPLE
    499 	{
    500 		sampleLength /= sizeof (double);
    501 		if (!allocateSmpData(s, sampleLength * sizeof (double), false))
    502 		{
    503 			loaderMsgBox("Not enough memory!");
    504 			return false;
    505 		}
    506 
    507 		if (fread(s->dataPtr, sampleLength, sizeof (double), f) != sizeof (double))
    508 		{
    509 			loaderMsgBox("General I/O error during loading! Is the file in use?");
    510 			return false;
    511 		}
    512 
    513 		// change endianness
    514 		int64_t *audioDataS64 = (int64_t *)s->dataPtr;
    515 		for (i = 0; i < sampleLength; i++)
    516 			audioDataS64[i] = SWAP64(audioDataS64[i]);
    517 
    518 		double *dAudioDataDouble = (double *)s->dataPtr;
    519 
    520 		// stereo conversion
    521 		if (numChannels == 2)
    522 		{
    523 			sampleLength /= 2;
    524 			switch (stereoSampleLoadMode)
    525 			{
    526 				case STEREO_SAMPLE_READ_LEFT:
    527 				{
    528 					// remove right channel data
    529 					for (i = 1; i < sampleLength; i++)
    530 						dAudioDataDouble[i] = dAudioDataDouble[(i * 2) + 0];
    531 				}
    532 				break;
    533 
    534 				case STEREO_SAMPLE_READ_RIGHT:
    535 				{
    536 					// remove left channel data
    537 					len32 = sampleLength - 1;
    538 					for (i = 0; i < len32; i++)
    539 						dAudioDataDouble[i] = dAudioDataDouble[(i * 2) + 1];
    540 
    541 					dAudioDataDouble[i] = 0.0;
    542 				}
    543 				break;
    544 
    545 				default:
    546 				case STEREO_SAMPLE_CONVERT:
    547 				{
    548 					// mix stereo to mono
    549 					len32 = sampleLength - 1;
    550 					for (i = 0; i < len32; i++)
    551 						dAudioDataDouble[i] = (dAudioDataDouble[(i * 2) + 0] + dAudioDataDouble[(i * 2) + 1]) * 0.5;
    552 
    553 					dAudioDataDouble[i] = 0.0;
    554 				}
    555 				break;
    556 			}
    557 		}
    558 
    559 		normalize64BitFloatToSigned16Bit(dAudioDataDouble, sampleLength);
    560 
    561 		int16_t *ptr16 = (int16_t *)s->dataPtr;
    562 		for (i = 0; i < sampleLength; i++)
    563 		{
    564 			const int32_t smp32 = (const int32_t)dAudioDataDouble[i];
    565 			ptr16[i] = (int16_t)smp32;
    566 		}
    567 
    568 		s->flags |= SAMPLE_16BIT;
    569 	}
    570 
    571 	if (sampleLength > MAX_SAMPLE_LEN)
    572 		sampleLength = MAX_SAMPLE_LEN;
    573 
    574 	bool sample16Bit = !!(s->flags & SAMPLE_16BIT);
    575 	reallocateSmpData(s, sampleLength, sample16Bit); // readjust memory needed
    576 
    577 	s->length = sampleLength;
    578 	s->volume = 64;
    579 	s->panning = 128;
    580 
    581 	setSampleC4Hz(s, dSampleRate);
    582 
    583 	return true;
    584 }
    585 
    586 static double getAIFFSampleRate(uint8_t *in)
    587 {
    588 	/* 80-bit IEEE-754 to unsigned double-precision float.
    589 	** Sign bit is ignored.
    590 	*/
    591 
    592 #define EXP_BIAS 16383
    593 
    594 	const uint16_t exp15 = ((in[0] & 0x7F) << 8) | in[1];
    595 	const uint64_t mantissaBits = *(uint64_t *)&in[2];
    596 	const uint64_t mantissa63 = SWAP64(mantissaBits) & INT64_MAX;
    597 
    598 	double dExp = exp15 - EXP_BIAS;
    599 	double dMantissa = mantissa63 / (INT64_MAX+1.0);
    600 
    601 	return (1.0 + dMantissa) * exp2(dExp);
    602 }
    603 
    604 static bool aiffIsStereo(FILE *f) // only ran on files that are confirmed to be AIFFs
    605 {
    606 	uint16_t numChannels;
    607 	uint32_t chunkID, chunkSize;
    608 
    609 	uint32_t oldPos = ftell(f);
    610 
    611 	fseek(f, 0, SEEK_END);
    612 	int32_t filesize = ftell(f);
    613 
    614 	if (filesize < 12)
    615 	{
    616 		fseek(f, oldPos, SEEK_SET);
    617 		return false;
    618 	}
    619 
    620 	fseek(f, 12, SEEK_SET);
    621 
    622 	uint32_t commPtr = 0;
    623 	uint32_t commLen = 0;
    624 
    625 	int32_t bytesRead = 0;
    626 	while (!feof(f) && bytesRead < filesize-12)
    627 	{
    628 		fread(&chunkID, 4, 1, f); chunkID = SWAP32(chunkID); if (feof(f)) break;
    629 		fread(&chunkSize, 4, 1, f); chunkSize = SWAP32(chunkSize); if (feof(f)) break;
    630 
    631 		int32_t endOfChunk = (ftell(f) + chunkSize) + (chunkSize & 1);
    632 		switch (chunkID)
    633 		{
    634 			case 0x434F4D4D: // "COMM"
    635 			{
    636 				commPtr = ftell(f);
    637 				commLen = chunkSize;
    638 			}
    639 			break;
    640 
    641 			default: break;
    642 		}
    643 
    644 		bytesRead += (chunkSize + (chunkSize & 1));
    645 		fseek(f, endOfChunk, SEEK_SET);
    646 	}
    647 
    648 	if (commPtr == 0 || commLen < 2)
    649 	{
    650 		fseek(f, oldPos, SEEK_SET);
    651 		return false;
    652 	}
    653 
    654 	fseek(f, commPtr, SEEK_SET);
    655 	fread(&numChannels, 2, 1, f); numChannels = SWAP16(numChannels);
    656 	fseek(f, oldPos, SEEK_SET);
    657 
    658 	return (numChannels == 2);
    659 }