This chapter contains sample applications that perform file operations using the digital media libraries.
Example 3-1 contains a listing of afinfo.c, which performs audio file recognition.
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <audiofile.h>
#include <audioutil.h>
#include <dmedia/dm_params.h>
#include <dmedia/dm_audio.h>
void myexit(int s) {
if(s != 0) fprintf(stderr, “\n\nexited with %d. oserror = %d\n”, s, oserror());
exit(s);
}
#define MAX_AWARE_OPTS 5
int legalMarkID(int* ids, int nids, int id) {
while(nids--)
if(*ids++ == id) return 1;
return 0;
}
typedef struct _maxamp {
float max[4];
int loc[4];
int timetag;
} maxamp;
void dump(char *, int);
main(int argc, char *argv[]) {
AFfilehandle handle;
int verbose = 0;
int sampfmt, sampwidth;
int fileformat, compression;
int channels;
int byteorder, numMiscs, numInsts, numMarkers, numCompTypes;
int numSupportedInsts, numSupportedInstParams;
int numSupportedLoops, numSupportedMarkers;
int defaultSampleFormat, defaultSampleWidth;
int arg = 1;
DMparams* formatParams;
double slope, intercept, minclip, maxclip;
if(argc < 2) {
fprintf(stderr, “Usage: %s [-v] filename1 [filename2 ...]\n”, argv[0]);
myexit(0);
}
if(!strcmp(argv[arg], “-v”)) {
verbose = 1;
arg++;
}
mallopt(M_DEBUG, 1);
for(; arg < argc; arg++) {
char* filename = argv[arg];
int* mids = NULL;
int fd = 0;
int track = AF_DEFAULT_TRACK;
struct stat _stat;
_stat.st_mode = 0; /* reset */
if(stat(filename, &_stat) < 0 || !(_stat.st_mode & S_IFREG))
continue;
fprintf(stderr, “\n**** %s Format Dump ****\n”, filename);
handle = afOpenFile(filename, “r”, AF_NULL_FILESETUP);
if(!handle) {
int err;
dmGetError(&err, NULL);
if(err == AF_BAD_NOT_IMPLEMENTED && (fd = open(filename, 0)) > 0)
fprintf(stderr, “Cannot read file (type %s)\n”,
(char *) afQueryPointer(AF_QUERYTYPE_FILEFMT, AF_QUERY_DESC,
afIdentifyNamedFD(fd, filename, NULL), 0, 0));
if(fd > 0) close(fd);
continue;
}
dmParamsCreate(&formatParams);
afGetFormatParams(handle, track, formatParams);
dmParamsDestroy(formatParams);
fileformat = afGetFileFormat(handle, 0);
fprintf(stderr, “File format: %s\n”,
(char *) afQueryPointer(AF_QUERYTYPE_FILEFMT,
AF_QUERY_NAME, fileformat, 0, 0));
fprintf(stderr, “Duration: %f seconds\n”,
afGetFrameCount(handle, track)/afGetRate(handle, track));
fprintf(stderr, “Framecount: %d\n”,
afGetFrameCount(handle, track));
fprintf(stderr, “Data Offset: %d bytes\n”,
afGetDataOffset(handle, track));
fprintf(stderr, “Total Data Size: %d bytes\n”,
afGetTrackBytes(handle, track));
afGetSampleFormat(handle, track, &sampfmt, &sampwidth);
fprintf(stderr, “Sample Format: %s, %d bits per sample\n”,
sampfmt == AF_SAMPFMT_TWOSCOMP ? “2's complement”
: sampfmt == AF_SAMPFMT_UNSIGNED ? “unsigned”
: sampfmt == AF_SAMPFMT_FLOAT ? “floating point”
: sampfmt == AF_SAMPFMT_DOUBLE ? “double-precision floating point”
: “unknown”,
sampwidth);
byteorder = afGetByteOrder(handle, track);
fprintf(stderr, “Byte order is %s-endian\n”,
byteorder == AF_BYTEORDER_BIGENDIAN ? “big” : “little”);
fprintf(stderr, “Samprate: %f\n”, afGetRate(handle, track));
fprintf(stderr, “Channel Count: %d\n”,
channels = afGetChannels(handle, track));
fprintf(stderr, “Frame Size: %.4f bytes\n”,
afGetFrameSize(handle, track, 0));
afGetPCMMapping(handle, track, &slope, &intercept, &minclip, &maxclip);
fprintf(stderr,
“PCM Mapping:\t slope: %.4f intercept: %.4f\n\t\tmin: %.4f
max: %.4f\n”, slope, intercept, minclip, maxclip);
compression = afGetCompression(handle, track);
fprintf(stderr, “Compression Type: %s\n”,
(char *) afQueryPointer(AF_QUERYTYPE_COMPRESSION,
AF_QUERY_NAME, compression, 0, 0));
if(compression == AF_COMPRESSION_MPEG1) {
int layer, target;
AUpvlist pvlist = AUpvnew(MAX_AWARE_OPTS);
AUpvsetparam (pvlist, 0, AF_MPEG_PARAM_LAYER);
AUpvsetvaltype(pvlist, 0, AU_PVTYPE_LONG);
AUpvsetparam (pvlist, 1, AF_MPEG_PARAM_BITRATE_TARGET);
AUpvsetvaltype(pvlist, 1, AU_PVTYPE_LONG);
afGetCompressionParams(handle, track,
&compression, pvlist, 2);
AUpvgetval(pvlist, 0, &layer);
AUpvgetval(pvlist, 1, &target);
fprintf(stderr, “\tCompression layer %d\n”,
layer==AF_MPEG_LAYER_I ? 1 : 2);
fprintf(stderr, “\tBit Rate: %d BPS\n”, target);
AUpvfree(pvlist);
}
else if(compression == AF_COMPRESSION_AWARE_MULTIRATE) {
int policy, target;
AUpvlist pvlist = AUpvnew(MAX_AWARE_OPTS);
AUpvsetparam (pvlist, 0, AF_AWARE_PARAM_BITRATE_POLICY);
AUpvsetvaltype(pvlist, 0, AU_PVTYPE_LONG);
afGetCompressionParams(handle, track,
&compression, pvlist, 1);
AUpvgetval(pvlist, 0, &policy);
fprintf(stderr, “\tCompression bitrate policy: %s\n”,
policy == AF_AWARE_FIXED_RATE ? “Fixed Rate”
: policy == AF_AWARE_CONST_QUAL ? “Constant Quality”
: policy == AF_AWARE_LOSSLESS ? “Lossless”
: “Unknown!”);
if(policy == AF_AWARE_FIXED_RATE) {
AUpvsetparam(pvlist, 0, AF_MPEG_PARAM_BITRATE_TARGET);
AUpvsetvaltype(pvlist, 0, AU_PVTYPE_LONG);
afGetCompressionParams(handle, track,
&compression, pvlist, 1);
AUpvgetval(pvlist, 0, &target);
fprintf(stderr, “\tBit Rate: %d BPS\n”, target);
}
AUpvfree(pvlist);
}
defaultSampleFormat = afQueryLong(AF_QUERYTYPE_FILEFMT,
AF_QUERY_SAMPLE_FORMATS, AF_QUERY_DEFAULT, fileformat, 0);
defaultSampleWidth = afQueryLong(AF_QUERYTYPE_FILEFMT,
AF_QUERY_SAMPLE_SIZES, AF_QUERY_DEFAULT, fileformat, 0);
if(verbose) {
fprintf(stderr, “Format's default sample format: %s width: %d\n”,
defaultSampleFormat == AF_SAMPFMT_TWOSCOMP ? “2's complement”
: defaultSampleFormat == AF_SAMPFMT_UNSIGNED ? “unsigned”
: defaultSampleFormat == AF_SAMPFMT_FLOAT ? “floating point”
: defaultSampleFormat == AF_SAMPFMT_DOUBLE ?
“double-precision floating point”
: “unknown”,
defaultSampleWidth);
fprintf(stderr, “\n”);
} /* verbose */
numCompTypes = afQueryLong(AF_QUERYTYPE_FILEFMT,
AF_QUERY_COMPRESSION_TYPES, AF_QUERY_VALUE_COUNT,
fileformat, 0);
if(verbose) {
fprintf(stderr, “This format supports %d compression type(s)”,
numCompTypes);
if(numCompTypes > 0) {
int i;
int* types = (int *) afQueryPointer(AF_QUERYTYPE_FILEFMT,
AF_QUERY_COMPRESSION_TYPES,
AF_QUERY_VALUES, fileformat,
0);
fprintf(stderr, “:\n”);
for(i = 0; i < numCompTypes; i++)
fprintf(stderr, “\t%s\n”,
(char *) afQueryPointer(AF_QUERYTYPE_COMPRESSION,
AF_QUERY_NAME, types[i], 0, 0));
free(types);
}
fprintf(stderr, “\n”);
} /* verbose */
if(verbose) {
numSupportedMarkers = afQueryLong(AF_QUERYTYPE_MARK,
AF_QUERY_MAX_NUMBER, fileformat, 0, 0);
fprintf(stderr, “This format supports %d mark(s)”,
numSupportedMarkers);
fprintf(stderr, “\n”);
} /* verbose */
numMarkers = afGetMarkIDs(handle, track, NULL);
if(numMarkers > 0) {
int m;
mids = (int *) calloc(numMarkers, sizeof(int));
afGetMarkIDs(handle, track, mids);
fprintf(stderr, “%d mark chunk(s) found:\n”, numMarkers);
for(m = 0; m < numMarkers; m++) {
fprintf(stderr,
“\tID: %d name: \”%s\”\tcomment: \”%s\”\tposition: %d\n”,
mids[m], afGetMarkName(handle, track, mids[m]),
afGetMarkComment(handle, track, mids[m]),
afGetMarkPosition(handle, track, mids[m])
);
}
}
numSupportedInsts = afQueryLong(AF_QUERYTYPE_INST, AF_QUERY_MAX_NUMBER,
fileformat, 0, 0);
numSupportedInstParams = afQueryLong(AF_QUERYTYPE_INSTPARAM,
AF_QUERY_ID_COUNT, fileformat,
0, 0);
if(verbose) {
fprintf(stderr, “This format supports %d inst chunk(s)”,
numSupportedInsts);
if(numSupportedInsts > 0) {
numSupportedLoops = afQueryLong(AF_QUERYTYPE_INST,
AF_QUERY_LOOPS, AF_QUERY_MAX_NUMBER, fileformat, 0);
fprintf(stderr, “, %d loop(s) per inst”, numSupportedLoops);
fprintf(stderr, “, and %d inst param(s)”, numSupportedInstParams);
}
fprintf(stderr, “\n\n”);
} /* verbose */
numInsts = afGetInstIDs(handle, NULL);
if(numInsts > 0) {
int i;
int* ids = (int *) calloc(numInsts, sizeof(int));
afGetInstIDs(handle, ids);
fprintf(stderr, “%d inst chunk(s) found:\n”, numInsts);
for(i = 0; i < numInsts; i++) {
int nLoops;
int *loops = NULL;
int instid = ids[i];
fprintf(stderr, “\tid %d:\n”, instid);
nLoops = afGetLoopIDs(handle, instid, NULL);
if(nLoops > 0) {
int l;
fprintf(stderr, “\t%d loop(s):\n”, nLoops);
loops = (int *) calloc(nLoops, sizeof(int));
afGetLoopIDs(handle, instid, loops);
for(l = 0; l < nLoops; l++) {
int mode = afGetLoopMode(handle, instid, loops[l]);
int stID = afGetLoopStart(handle, instid, loops[l]);
int endID = afGetLoopEnd(handle, instid, loops[l]);
fprintf(stderr,
“\t\ttrackID: %d mode: %s\tstartID: %d\tendID: %d\n”,
afGetLoopTrack(handle, instid, loops[l]),
mode == AF_LOOP_MODE_NOLOOP ? “ignored” :
mode == AF_LOOP_MODE_FORW ? “forward” :
“forward/backward”,
legalMarkID(mids, numMarkers, stID) ? stID : stID,
legalMarkID(mids, numMarkers, endID) ? endID : endID
);
}
cfree(loops);
}
if(numSupportedInstParams > 0) {
int i;
int *paramIDs = (int *) afQueryPointer(
AF_QUERYTYPE_INSTPARAM, AF_QUERY_IDS, fileformat, 0, 0);
fprintf(stderr, “\t%d paramID(s):\n”,
numSupportedInstParams);
for(i = 0; i < numSupportedInstParams; i++)
fprintf(stderr, “\t\tID: %d Name: \”%s\” Value: %d\n”,
paramIDs[i],
(char *) afQueryPointer(AF_QUERYTYPE_INSTPARAM,
AF_QUERY_NAME,
fileformat,
paramIDs[i], 0),
afGetInstParamLong(handle, instid, paramIDs[i]));
cfree(paramIDs);
}
}
cfree(ids);
}
if(verbose) {
numMiscs = afQueryLong(AF_QUERYTYPE_MISC,
AF_QUERY_TYPE_COUNT, fileformat, 0, 0);
fprintf(stderr, “This format supports %d MISC chunk type(s)”, numMiscs);
if(numMiscs > 0) {
int i;
int* miscs = (int *) afQueryPointer(AF_QUERYTYPE_MISC,
AF_QUERY_TYPES, fileformat,
0, 0);
fprintf(stderr, “:\n”);
for(i = 0; i < numMiscs; i++)
fprintf(stderr, “\tType: %d Name: \”%s\”\n”,
miscs[i],
(char *) afQueryPointer(AF_QUERYTYPE_MISC,
AF_QUERY_NAME, miscs[i], 0, 0));
free(miscs);
}
fprintf(stderr, “\n”);
} /* verbose */
numMiscs = afGetMiscIDs(handle, 0);
if(numMiscs > 0) {
int i;
int* miscIDs = calloc(numMiscs, sizeof(int));
int miscType, miscSize;
char* miscBuf = NULL;
char* typeName = “unknown”;
afGetMiscIDs(handle, miscIDs);
fprintf(stderr, “Misc chunks present in file:\n”);
for(i = 0; i < numMiscs; i++) {
miscType = afGetMiscType(handle, miscIDs[i]);
miscSize = afGetMiscSize(handle, miscIDs[i]);
typeName = (char *) afQueryPointer(AF_QUERYTYPE_MISC,
AF_QUERY_NAME,
miscType, 0, 0);
fprintf(stderr, “\tType: `%s' [%d] Size: %d\n”,
typeName, miscType, miscSize);
if(miscSize > 0) {
miscBuf = calloc(miscSize, 1);
afReadMisc(handle, miscIDs[i], miscBuf, miscSize);
}
if(miscType != AF_MISC_UNRECOGNIZED
&& miscType != AF_MISC_APPL
&& miscType != AF_MISC_MIDI
&& miscType != AF_MISC_PCMMAP
&& miscType != AF_MISC_IRCAM_PEAKAMP) {
char c;
char* m = miscBuf;
fprintf(stderr, “\tMisc chunk text:\n\t\t\””);
while(miscSize-- > 0) {
if(*m && isascii(c = *m++)) fprintf(stderr, “%c”, c);
else if(miscSize > 1) fprintf(stderr, “ “);
}
fprintf(stderr, “\”\n”);
}
else if (miscType == AF_MISC_IRCAM_PEAKAMP) {
if(miscSize >= sizeof(maxamp)) {
int c;
maxamp* amp = (maxamp *) miscBuf;
fprintf(stderr, “\tPeak amp information:\n”);
for(c = 0; c < channels; c++)
fprintf(stderr, “\t\tChan %d: peak: %f loc: %d\n”,
c, amp->max[c], amp->loc[c]);
fprintf(stderr, “\tCreation time: %d\n”, amp->timetag);
}
else fprintf(stderr, “\t CORRUPTED MAXAMP: size %d < %d\n”,
miscSize, sizeof(maxamp));
}
else {
fprintf(stderr, “\tMisc chunk dump:\n\n”);
dump(miscBuf, miscSize);
fprintf(stderr, “\n\n”);
}
if(miscBuf) cfree(miscBuf);
miscBuf = NULL;
}
cfree(miscIDs);
}
cfree(mids);
afCloseFile(handle);
}
}
int base = 16;
void dump(char *b, int bufsize) {
unsigned char buf[17];
int ct, bytes, remaining = bufsize, offset = -16,cu,az = 0;
while (remaining) {
bytes = remaining > 16 ? 16 : remaining;
bcopy(b, buf, bytes);
remaining -= bytes;
ct = bytes;
for (cu = 0; cu != ct; cu++)
if (buf[cu])
break;
if (cu == 16)
if (az) {
if (az == 1)
fprintf(stderr, “*\n”);
az = 2;
offset += 16;
continue;
}
else
az = 1;
else
az = 0;
buf[ct] = `\0';
if (base==16)
fprintf(stderr, “%08x: “,offset += 16);
else if (base==8)
fprintf(stderr, “%08o: “,offset += 16);
else
fprintf(stderr, “%08d: “,offset += 16);
for (cu = 0; cu != ct; cu++)
fprintf(stderr, ((cu & 3) == 3) ? “%02x “ : “%02x”,(int) buf[cu]);
fprintf(stderr, “%*s”,40-(ct*2+ct/4),””);
for (cu = 0; cu != ct; cu++)
if (buf[cu] < ` ` || buf[cu] >= `\x7f')
buf[cu] = `.';
fprintf(stderr, “%s\n”,buf);
}
}
|