int main (int argc, const char * argv[]) { if (argc == 1) { fprintf (stderr, "%s\n", usageStr); exit(0); } char* filePath = 0; bool shouldPlay = false; bool shouldSetBank = false; bool shouldUseMIDIEndpoint = false; bool shouldPrint = true; bool waitAtEnd = false; bool diskStream = false; OSType dataFormat = 0; Float64 srate = 0; const char* outputFilePath = 0; MusicSequenceLoadFlags loadFlags = 0; char* bankPath = 0; Float32 startTime = 0; UInt32 numFrames = 512; for (int i = 1; i < argc; ++i) { if (!strcmp ("-p", argv[i])) { shouldPlay = true; } else if (!strcmp ("-w", argv[i])) { waitAtEnd = true; } else if (!strcmp ("-d", argv[i])) { diskStream = true; } else if (!strcmp ("-b", argv[i])) { shouldSetBank = true; if (++i == argc) goto malformedInput; bankPath = const_cast<char*>(argv[i]); } else if (!strcmp ("-n", argv[i])) { shouldPrint = false; } else if ((filePath == 0) && (argv[i][0] == '/' || argv[i][0] == '~')) { filePath = const_cast<char*>(argv[i]); } else if (!strcmp ("-t", argv[i])) { if (++i == argc) goto malformedInput; sscanf (argv[i], "%f", &startTime); } else if (!strcmp("-e", argv[i])) { shouldUseMIDIEndpoint = true; } else if (!strcmp("-c", argv[i])) { loadFlags = kMusicSequenceLoadSMF_ChannelsToTracks; } else if (!strcmp ("-i", argv[i])) { if (++i == argc) goto malformedInput; sscanf (argv[i], "%ld", &numFrames); } else if (!strcmp ("-f", argv[i])) { if (i + 3 >= argc) goto malformedInput; outputFilePath = argv[++i]; str2OSType (argv[++i], dataFormat); sscanf (argv[++i], "%lf", &srate); } else { malformedInput: fprintf (stderr, "%s\n", usageStr); exit (1); } } if (filePath == 0) { fprintf (stderr, "You have to specify a MIDI file to print or play\n"); fprintf (stderr, "%s\n", usageStr); exit (1); } if (shouldUseMIDIEndpoint && outputFilePath) { printf ("can't write a file when you try to play out to a MIDI Endpoint\n"); exit (1); } MusicSequence sequence; OSStatus result; require_noerr (result = LoadSMF (filePath, sequence, loadFlags), fail); if (shouldPrint) CAShow (sequence); if (shouldPlay) { AUGraph graph = 0; AudioUnit theSynth = 0; require_noerr (result = MusicSequenceGetAUGraph (sequence, &graph), fail); require_noerr (result = AUGraphOpen (graph), fail); require_noerr (result = GetSynthFromGraph (graph, theSynth), fail); require_noerr (result = AudioUnitSetProperty (theSynth, kAudioUnitProperty_CPULoad, kAudioUnitScope_Global, 0, &maxCPULoad, sizeof(maxCPULoad)), fail); if (shouldUseMIDIEndpoint) { MIDIClientRef theMidiClient; MIDIClientCreate(CFSTR("Play Sequence"), NULL, NULL, &theMidiClient); ItemCount destCount = MIDIGetNumberOfDestinations(); if (destCount == 0) { fprintf (stderr, "No MIDI Endpoints to play to.\n"); exit(1); } require_noerr (result = MusicSequenceSetMIDIEndpoint (sequence, MIDIGetDestination(0)), fail); } else { if (shouldSetBank) { FSRef soundBankRef; require_noerr (result = FSPathMakeRef ((const UInt8*)bankPath, &soundBankRef, 0), fail); printf ("Setting Sound Bank:%s\n", bankPath); require_noerr (result = AudioUnitSetProperty (theSynth, kMusicDeviceProperty_SoundBankFSRef, kAudioUnitScope_Global, 0, &soundBankRef, sizeof(soundBankRef)), fail); } if (diskStream) { UInt32 value = diskStream; require_noerr (result = AudioUnitSetProperty (theSynth, kMusicDeviceProperty_StreamFromDisk, kAudioUnitScope_Global, 0, &value, sizeof(value)), fail); } if (outputFilePath) { // need to tell synth that is going to render a file. UInt32 value = 1; require_noerr (result = AudioUnitSetProperty (theSynth, kAudioUnitProperty_OfflineRender, kAudioUnitScope_Global, 0, &value, sizeof(value)), fail); } require_noerr (result = SetUpGraph (graph, numFrames, srate, (outputFilePath != NULL)), fail); if (shouldPrint) { printf ("Sample Rate: %.1f \n", srate); printf ("Disk Streaming is enabled: %c\n", (diskStream ? 'T' : 'F')); } require_noerr (result = AUGraphInitialize (graph), fail); if (shouldPrint) CAShow (graph); } MusicPlayer player; require_noerr (result = NewMusicPlayer (&player), fail); require_noerr (result = MusicPlayerSetSequence (player, sequence), fail); // figure out sequence length UInt32 ntracks; require_noerr(MusicSequenceGetTrackCount (sequence, &ntracks), fail); MusicTimeStamp sequenceLength = 0; for (UInt32 i = 0; i < ntracks; ++i) { MusicTrack track; MusicTimeStamp trackLength; UInt32 propsize = sizeof(MusicTimeStamp); require_noerr (result = MusicSequenceGetIndTrack(sequence, i, &track), fail); require_noerr (result = MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength, &trackLength, &propsize), fail); if (trackLength > sequenceLength) sequenceLength = trackLength; } // now I'm going to add 8 beats on the end for the reverb/long releases to tail off... sequenceLength += 8; require_noerr (result = MusicPlayerSetTime (player, startTime), fail); require_noerr (result = MusicPlayerPreroll (player), fail); if (shouldPrint) { printf ("Ready to play: %s, %.2f beats long\n\t<Enter> to continue: ", filePath, sequenceLength); getc(stdin); } startRunningTime = AudioGetCurrentHostTime (); require_noerr (result = MusicPlayerStart (player), fail); if (outputFilePath) WriteOutputFile (outputFilePath, dataFormat, srate, sequenceLength, shouldPrint, graph, numFrames, player); else PlayLoop (player, graph, sequenceLength, shouldPrint, waitAtEnd); require_noerr (result = MusicPlayerStop (player), fail); if (shouldPrint) printf ("finished playing\n"); // this shows you how you should dispose of everything require_noerr (result = DisposeMusicPlayer (player), fail); require_noerr (result = DisposeMusicSequence(sequence), fail); // don't own the graph so don't dispose it (the seq owns it as we never set it ourselves, we just got it....) } else { require_noerr (result = DisposeMusicSequence(sequence), fail); } while (waitAtEnd) CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.25, false); return 0; fail: if (shouldPrint) printf ("Error = %ld\n", result); return result; }
int main (int argc, const char * argv[]) { char* filePath = NULL; bool overwrite = false; ComponentDescription compDesc = {0, 0, 0, 0, 0}; AudioFileID inputFileID = 0; AudioFileID outputFileID = 0; CAStreamBasicDescription desc; AudioUnit theUnit = 0; setbuf (stdout, NULL); for (int i = 1; i < argc; ++i) { if (strcmp (argv[i], "-u") == 0) { if ( (i + 3) < argc ) { compDesc.componentType = str2OSType (argv[i + 1]); compDesc.componentSubType = str2OSType (argv[i + 2]); compDesc.componentManufacturer = str2OSType (argv[i + 3]); Component comp = FindNextComponent (NULL, &compDesc); if (comp == NULL) break; OpenAComponent (comp, &theUnit); i += 3; } else { printf ("Which Component:\n%s", usageStr); return -1; } } else if (strcmp (argv[i], "-f") == 0) { filePath = const_cast<char*>(argv[++i]); printf ("Input File:%s\n", filePath); } else if (strcmp (argv[i], "-o") == 0) { overwrite = true; } else { printf ("%s\n", usageStr); return -1; } } if (compDesc.componentType == 0) { printf ("Must specify AU:\n%s\n", usageStr); return -1; } if (theUnit == 0) { printf ("Can't find specified unit\n"); return -1; } if (filePath == NULL) { printf ("Must specify file to process:\n%s\n", usageStr); return -1; } OSStatus result = 0; if (result = InputFile (filePath, inputFileID)) { printf ("Result = %ld, parsing input file, exit...\n", result); return result; } UInt32 fileType; UInt32 size = sizeof (fileType); result = AudioFileGetProperty (inputFileID, kAudioFilePropertyFileFormat, &size, &fileType); if (result) { printf ("Error getting File Type of input file:%ld, exit...\n", result); return result; } size = sizeof (desc); result = AudioFileGetProperty (inputFileID, kAudioFilePropertyDataFormat, &size, &desc); if (result) { printf ("Error getting File Format of input file:%ld, exit...\n", result); return result; } if (desc.IsPCM() == false) { printf ("Only processing linear PCM file types and data:\n"); desc.Print(); return -1; } result = OutputFile (filePath, fileType, compDesc.componentSubType, overwrite, desc, outputFileID); if (result) { printf ("Error creating output file:%ld, exit...\n", result); return result; } // at this point we're ready to process return Process (theUnit, compDesc, inputFileID, desc, outputFileID); }
void ParseArgs (int argc, char * const argv[], AudioFileTypeID & outFormat, Float64 & outSampleRate, OSType & outFileType, CFURLRef& outInputFileURL, CFURLRef& outOutputFileURL, UInt32 & outBitDepth, UInt32 & outBitRate) { if (argc < 2) { printf ("No Input File specified\n"); UsageString(1); } // support "ConvertFile -h" usage if (argc == 2 && !strcmp("-h", argv[1])) { UsageString(0); } // first validate our initial condition const char* inputFileName = argv[1]; outInputFileURL = CFURLCreateFromFileSystemRepresentation (kCFAllocatorDefault, (const UInt8 *)inputFileName, strlen(inputFileName), false); if (!outInputFileURL) { printf ("* * Bad input file path\n"); UsageString(1); } outBitRate = 0; outBitDepth = 0; // look to see if a format or different file output has been specified for (int i = 2; i < argc; ++i) { if (!strcmp ("-d", argv[i])) { str2OSType (argv[++i], outFormat); outSampleRate = 0; } else if (!strcmp ("-r", argv[i])) { sscanf (argv[++i], "%lf", &outSampleRate); outFormat = 0; } else if (!strcmp("-bd", argv[i])) { int temp; sscanf (argv[++i], "%d", &temp); outBitDepth = temp; } else if (!strcmp ("-f", argv[i])) { str2OSType (argv[++i], outFileType); } else if (!strcmp ("-b", argv[i])) { int temp; sscanf (argv[++i], "%u", &temp); outBitRate = temp; } else if (!strcmp ("-h", argv[i])) { UsageString(0); } else { printf ("* * Unknown command: %s\n", argv[i]); UsageString(1); } } // output file UInt32 size = sizeof(CFArrayRef); CFArrayRef extensions; OSStatus err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_ExtensionsForType, sizeof(OSType), &outFileType, &size, &extensions); XThrowIfError (err, "Getting the file extensions for file type"); // just take the first extension CFStringRef ext = (CFStringRef)CFArrayGetValueAtIndex(extensions, 0); char extstr[32]; Boolean res = CFStringGetCString(ext, extstr, 32, kCFStringEncodingUTF8); XThrowIfError (!res, "CFStringGetCString"); // release the array as we're done with this now CFRelease (extensions); char outFname[256]; #if TARGET_OS_WIN32 char drive[3], dir[256]; _splitpath_s(inputFileName, drive, 3, dir, 256, NULL, 0, NULL, 0); _makepath_s(outFname, 256, drive, dir, "outfile", extstr); #else // char outFname[64]; sprintf (outFname, "/tmp/outfile.%s", extstr); #endif outOutputFileURL = CFURLCreateFromFileSystemRepresentation (kCFAllocatorDefault, (const UInt8 *)outFname, strlen(outFname), false); if (!outOutputFileURL) { printf ("* * Bad output file path\n"); UsageString(1); } }