Chapter 3. Digital Media File Operations Examples
Prev |  | Next

## Chapter 3. Digital Media File Operations Examples

This chapter contains sample applications that perform file operations using the digital media libraries.

## Audio File Recognition

Example 3-1 contains a listing of `afinfo.c`, which performs audio file recognition.

Example 3-1. Audio File Recognition: `afinfo.c`

    #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);
        }
    }

Prev | Table of Contents | Next
Chapter 2. Digital Media Data Conversion Examples |  | Chapter 4. Digital Media I/O Examples