Skip to content

Instantly share code, notes, and snippets.

@lalawue
Created January 28, 2015 15:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lalawue/3c9a210d9816767050b9 to your computer and use it in GitHub Desktop.
Save lalawue/3c9a210d9816767050b9 to your computer and use it in GitHub Desktop.
Read .aiff audio file format and save the raw data
/*
* Copyright (c) 2015 lalawue
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the MIT license. See LICENSE for details.
*/
#include <stdio.h>
#include <string>
#include <vector>
#include <math.h>
#include <stdlib.h>
using namespace std;
static const int SHORT_MAX = 0xFFFF/2;
unsigned long swapByteOrderULong(unsigned long org) {
unsigned long ret = 0;
unsigned char *p = (unsigned char *)&ret;
p[3] = (org & 0x000000FF);
p[2] = (org & 0x0000FF00) >> 8;
p[1] = (org & 0x00FF0000) >> 16;
p[0] = (org & 0xFF000000) >> 24;
return ret;
}
unsigned short swapByteOrderUShort(unsigned short org){
return ((org & 0xFF00) >> 8) | ((org & 0x00FF) << 8);
}
signed short swapByteOrderShort(signed short org){
return ((org & 0xFF00) >> 8) | ((org & 0x00FF) << 8);
}
# define FloatToUnsigned(f) ((unsigned long)(((long)(f - 2147483648.0)) + 2147483647L) + 1)
#ifndef HUGE_VAL
#define HUGE_VAL HUGE
#endif /*HUGE_VAL*/
void ConvertToIeeeExtended(double num, char* bytes)
{
int sign;
int expon;
double fMant, fsMant;
unsigned long hiMant, loMant;
if (num < 0) {
sign = 0x8000;
num *= -1;
} else {
sign = 0;
}
if (num == 0) {
expon = 0; hiMant = 0; loMant = 0;
}
else {
fMant = frexp(num, &expon);
if ((expon > 16384) || !(fMant < 1)) { /* Infinity or NaN */
expon = sign|0x7FFF; hiMant = 0; loMant = 0; /* infinity */
}
else { /* Finite */
expon += 16382;
if (expon < 0) { /* denormalized */
fMant = ldexp(fMant, expon);
expon = 0;
}
expon |= sign;
fMant = ldexp(fMant, 32);
fsMant = floor(fMant);
hiMant = FloatToUnsigned(fsMant);
fMant = ldexp(fMant - fsMant, 32);
fsMant = floor(fMant);
loMant = FloatToUnsigned(fsMant);
}
}
bytes[0] = expon >> 8;
bytes[1] = expon;
bytes[2] = hiMant >> 24;
bytes[3] = hiMant >> 16;
bytes[4] = hiMant >> 8;
bytes[5] = hiMant;
bytes[6] = loMant >> 24;
bytes[7] = loMant >> 16;
bytes[8] = loMant >> 8;
bytes[9] = loMant;
}
# define UnsignedToFloat(u) (((double)((long)(u - 2147483647L - 1))) + 2147483648.0)
double ConvertFromIeeeExtended(unsigned char* bytes /* LCN */)
{
double f;
int expon;
unsigned long hiMant, loMant;
expon = ((bytes[0] & 0x7F) << 8) | (bytes[1] & 0xFF);
hiMant = ((unsigned long)(bytes[2] & 0xFF) << 24)
| ((unsigned long)(bytes[3] & 0xFF) << 16)
| ((unsigned long)(bytes[4] & 0xFF) << 8)
| ((unsigned long)(bytes[5] & 0xFF));
loMant = ((unsigned long)(bytes[6] & 0xFF) << 24)
| ((unsigned long)(bytes[7] & 0xFF) << 16)
| ((unsigned long)(bytes[8] & 0xFF) << 8)
| ((unsigned long)(bytes[9] & 0xFF));
if (expon == 0 && hiMant == 0 && loMant == 0) {
f = 0;
}
else {
if (expon == 0x7FFF) { /* Infinity or NaN */
f = HUGE_VAL;
}
else {
expon -= 16383;
f = ldexp(UnsignedToFloat(hiMant), expon-=31);
f += ldexp(UnsignedToFloat(loMant), expon-=32);
}
}
if (bytes[0] & 0x80)
return -f;
else
return f;
}
void
_loadFile(char *_fileName, char *out_file_name)
{
// vector<float> _left;
// vector<float> _right;
// _left.clear();
// _right.clear();
printf("size of unsigned long=%ld\n", sizeof(unsigned long));
FILE *fp;
if ((fp = fopen(_fileName,"rb")) == NULL){
printf("can't open file:%s.\n", _fileName);
return ;
}
printf("reading file : %s\n", _fileName);
//read "FORM" chunk
char str[5];
str[4] = 0;
fread(str,1,4,fp);
printf("%s\n", str); //Should be FORM
unsigned long size;
fread(&size, 4,1, fp);
size = swapByteOrderULong(size);
printf("size = 0x%lx(%ld bytes)\n", size,size);
//read "AIFF" formType tag
char formType[5];
formType[4] = 0;
fread(formType,1,4,fp);
printf("%s\n", formType);
//chunks ("COMM", "SSND",etc).
char chunkName[5];
chunkName[4] = 0;
fread(chunkName,1,4,fp);
printf("%s\n", chunkName);
fread(&size, 4,1, fp);
size = swapByteOrderULong(size);
printf("size = 0x%lx(%ld bytes)\n", size,size);
int prevPos = ftell(fp);
unsigned short channels = 0;
unsigned long sampleFrames = 0;
string cName = chunkName;
if (cName == "COMM") {
printf("COMM chunk dumping\n");
{ //parse Comm chunk
unsigned short bitSize = 0;
unsigned char sampleRateBytes[10];
fread(&channels, 2 ,1 , fp);
channels = swapByteOrderUShort(channels);
fread(&sampleFrames, 4, 1, fp);
sampleFrames = swapByteOrderULong(sampleFrames);
fread(&bitSize, 2, 1, fp);
bitSize = swapByteOrderUShort(bitSize);
fread(&sampleRateBytes, 1, 10, fp);
double sampleRate = ConvertFromIeeeExtended(sampleRateBytes);
printf("%d channels, %d bits, %.2f[Hz], %ld samples\n", channels, bitSize, sampleRate, sampleFrames);
double duration = (double)sampleFrames / sampleRate;
printf("%.2f [seconds]\n", duration);
}
}
fseek(fp,prevPos, SEEK_SET);
fseek(fp,size,SEEK_CUR);
chunkName[4] = 0;
fread(chunkName,1,4,fp);
printf("%s\n", chunkName);
fread(&size, 4,1, fp);
size = swapByteOrderULong(size);
printf("size = 0x%lx(%ld bytes)\n", size, size);
cName = chunkName;
if (cName == "SSND") {
printf("dumping SSND chunk\n");
unsigned long offset = 0;
unsigned long blockSize = 0;
fread(&offset, 4, 1, fp);
fread(&blockSize, 4, 1, fp);
offset = swapByteOrderULong(offset);
blockSize = swapByteOrderULong(blockSize);
printf("offset = %ld, blockSize = %ld\n", offset, blockSize);
}
printf("loading buffers...");
//if (channels == 1){ //assuming stereo only?
//ensure size.
signed short *samples = (short*)malloc(sizeof(short) * sampleFrames*channels);
fread(samples, 2, sampleFrames*channels, fp);
unsigned short *result = (unsigned short*)malloc(sizeof(*result) *sampleFrames*channels);
printf("sampleFrames = %ld, %ld\n", sampleFrames, sizeof(*result));
for (int i = 0; i < sampleFrames*channels ; i++){
//_stlbuffer.push_back(swapByteOrderShort(samples[i]));
// float val = swapByteOrderShort(samples[i]);
// val /= SHORT_MAX;
// val *= 0.99; //avoid clipping.
// if (0 == (i % 2)) {
// _left.push_back(val);
// } else {
// _right.push_back(val);
// }
result[i] = swapByteOrderShort(samples[i]);
}
{
FILE *wfp = fopen(out_file_name, "wb");
fwrite(result, sizeof(*result), sampleFrames*channels, wfp);
fclose(wfp);
}
//printf("STL Buffer array size = %lu\n", _stlbuffer.size());
fclose(fp);
}
int main(int argc, char *argv[]) {
if (argc < 3) {
printf("%s aiff_file out_sample\n", argv[0]);
return 0;
}
_loadFile(argv[1], argv[2]);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment