Skip to content

Commit 9814959

Browse files
mynameisjohnsgretscher
authored andcommitted
Adding iXML chunk support to AudioFile class - see http://ixml.info
1 parent b04337b commit 9814959

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

AudioFile.cpp

+54
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "AudioFile.h"
1212
#include "MathDefs.h"
1313
#include <climits>
14+
#include <cstring>
1415
#include <utility>
1516

1617
#ifdef _WIN32 // Windows specific
@@ -39,6 +40,7 @@
3940
#define F_F32 0x32336c66 // supported AIFF data compression
4041
#define F_F32CSND 0x32334c46 // tags: NONE, float (std + CSound)
4142
#define F_NONE 0x454e4f4e //
43+
#define T_IXML 0x4C4D5869 // http://www.ixml.info/
4244

4345
namespace icstdsp { // begin library specific namespace
4446

@@ -65,6 +67,8 @@ AudioFile::AudioFile()
6567
resolution = 0; // resolution in bit
6668
channels = 0; // number of channels
6769
spkpos = 0; // speaker positions
70+
iXMLData = NULL; // iXML data
71+
iXMLDataSize = 0; // iXML data size
6872
}
6973

7074
AudioFile::AudioFile (AudioFile&& src)
@@ -84,12 +88,15 @@ AudioFile& AudioFile::operator = (AudioFile&& src)
8488
std::swap(spkpos, src.spkpos);
8589
std::swap(resolution, src.resolution);
8690
std::swap(channels, src.channels);
91+
std::swap(iXMLData, src.iXMLData);
92+
std::swap(iXMLDataSize, src.iXMLDataSize);
8793
return *this;
8894
}
8995

9096
AudioFile::~AudioFile()
9197
{
9298
if (audio) {delete[] audio;}
99+
SetiXMLData(NULL, 0);
93100
}
94101

95102
// create new audio file
@@ -297,6 +304,16 @@ int AudioFile::LoadWave(unsigned int offset, unsigned int frames, bool nodata)
297304
}
298305
else {return NOSUPPORT;}
299306

307+
SetiXMLData(NULL, 0);
308+
if (GotoChunk(T_IXML, false))
309+
{
310+
fread(&chunksize, sizeof(int), 1, file);
311+
try {iXMLData = new unsigned char[chunksize];} catch(...) {iXMLData = NULL;}
312+
if (iXMLData == NULL) {return NOMEMORY;}
313+
fread(iXMLData, 1, chunksize, file);
314+
iXMLDataSize = chunksize;
315+
}
316+
300317
// update properties and clean up
301318
size = psize; resolution = presolution; channels = pchannels; rate = prate;
302319
spkpos = pspkpos;
@@ -337,6 +354,16 @@ int AudioFile::LoadAiff(unsigned int offset, unsigned int frames, bool nodata)
337354
if ((presolution == 0) || (pchannels == 0)) {return CORRUPT;}
338355
bytesperword = 1 + (presolution-1)/8;
339356

357+
SetiXMLData(NULL, 0);
358+
if (GotoChunk(T_IXML, false))
359+
{
360+
fread(&chunksize, sizeof(int), 1, file);
361+
try {iXMLData = new unsigned char[chunksize];} catch(...) {iXMLData = NULL;}
362+
if (iXMLData == NULL) {return NOMEMORY;}
363+
fread(iXMLData, 1, chunksize, file);
364+
iXMLDataSize = chunksize;
365+
}
366+
340367
// go back to the end of the form chunk and start searching for a
341368
// sound data chunk skipping other chunks, jump to start of audio data,
342369
// AIFF files without audio data do not require a sound chunk
@@ -715,6 +742,8 @@ int AudioFile::SaveWave(const char *filename)
715742
else {allcsize = 36 + audiobytes + fill; fmtcsize = 16;}
716743
if (bytesperword > 3) {usefloat = true;}
717744

745+
if (iXMLData) allcsize += (8 + iXMLDataSize) + (iXMLDataSize % 2);
746+
718747
// open file
719748
if (filename[0] == 0) return NOFILE;
720749
if ((file = fopen(filename,"wb")) == NULL) return NOFILE;
@@ -811,6 +840,14 @@ int AudioFile::SaveWave(const char *filename)
811840
delete[] buf;
812841
}
813842

843+
if (iXMLData)
844+
{
845+
data32 = T_IXML; fwrite(&data32, sizeof (int), 1, file);
846+
data32 = iXMLDataSize; fwrite(&data32, sizeof (int), 1, file);
847+
fwrite(iXMLData, 1, data32, file);
848+
if (iXMLDataSize % 2) { const char space = ' '; fwrite(&space, 1, 1, file); }
849+
}
850+
814851
// clean up
815852
fclose(file);
816853
return 0;
@@ -977,6 +1014,23 @@ float* AudioFile::GetSafePt(unsigned int channel, bool lock)
9771014
return audio + channel*size;
9781015
}
9791016

1017+
// return iXML chunk data bytes
1018+
const unsigned char* AudioFile::GetiXMLData(unsigned int* dataLength) const
1019+
{
1020+
*dataLength = iXMLDataSize;
1021+
return iXMLData;
1022+
}
1023+
1024+
// set/clear iXML chunk data bytes
1025+
void AudioFile::SetiXMLData(const unsigned char* data, unsigned int dataLength)
1026+
{
1027+
if (iXMLData) {delete[] iXMLData;}
1028+
try {iXMLData = new unsigned char[dataLength];} catch(...) {iXMLData = NULL;}
1029+
if (iXMLData == NULL) {iXMLDataSize = 0; return;}
1030+
memcpy(iXMLData, data, dataLength);
1031+
iXMLDataSize = dataLength;
1032+
}
1033+
9801034
// return array size in frames (samples / channels)
9811035
unsigned int AudioFile::GetSize() const {return size;}
9821036

AudioFile.h

+6
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ class AudioFile
106106
// properties remain unchanged until next
107107
// call with false, locks Create/Load(Raw)
108108
// in a wait state during this time!
109+
const unsigned char* GetiXMLData ( // return iXML chunk data bytes
110+
unsigned int* dataLength) const;
111+
void SetiXMLData ( // set/clear iXML chunk data bytes
112+
const unsigned char* data, unsigned int dataLength);
109113
private: //*** see AudioFile.cpp for details ***
110114
FILE* file;
111115
float* audio;
@@ -125,6 +129,8 @@ class AudioFile
125129
bool GotoChunk(unsigned int tag, bool bigendian);
126130
AudioFile& operator = (const AudioFile& src);
127131
AudioFile(const AudioFile& src);
132+
unsigned char* iXMLData;
133+
unsigned int iXMLDataSize;
128134
};
129135

130136
} // end library specific namespace

0 commit comments

Comments
 (0)