Exemplo n.º 1
0
void set_stream()
{
    OSStatus err;
    UInt32 propertySize;

    // get the magic cookie, if any, from the converter
    err = AudioQueueGetPropertySize(d_owner->queue,
                                    kAudioConverterCompressionMagicCookie,
                                    &propertySize);

    if (err == noErr && propertySize > 0) {
        // there is valid cookie data to be fetched;  get it
        Byte *magicCookie = (Byte *)malloc(propertySize);
        err = AudioQueueGetProperty(d_owner->queue,
                                    kAudioConverterCompressionMagicCookie,
                                    magicCookie,
                                    &propertySize);
        if (err == 0)
        {
            // now set the magic cookie on the output file
            // even though some formats have cookies, some files don't take them, so we ignore the error
            /*err =*/
            AudioFileSetProperty(d_owner->stm,
                                 kAudioFilePropertyMagicCookieData,
                                 propertySize,
                                 magicCookie);
        }
        free(magicCookie);
    }

    /*
     if (err != 0)
     trace_fmt("failed to set stream, %.4s", &err);
     */
}
// Some audio formats have a magic cookie associated with them which is required to decompress audio data
// When converting audio, a magic cookie may be returned by the Audio Converter so that it may be stored along with
// the output data -- This is done so that it may then be passed back to the Audio Converter at a later time as required
static void WriteCookie(AudioConverterRef converter, AudioFileID destinationFileID)
{
    // grab the cookie from the converter and write it to the destinateion file
	UInt32 cookieSize = 0;
	OSStatus error = AudioConverterGetPropertyInfo(converter, kAudioConverterCompressionMagicCookie, &cookieSize, NULL);
    
    // if there is an error here, then the format doesn't have a cookie - this is perfectly fine as some formats do not
	if (noErr == error && 0 != cookieSize) {
		char* cookie = new char [cookieSize];
		
		error = AudioConverterGetProperty(converter, kAudioConverterCompressionMagicCookie, &cookieSize, cookie);
        if (noErr == error) {
            error = AudioFileSetProperty(destinationFileID, kAudioFilePropertyMagicCookieData, cookieSize, cookie);
            if (noErr == error) {
                printf("Writing magic cookie to destination file: %ld\n", cookieSize);
            } else {
                printf("Even though some formats have cookies, some files don't take them and that's OK\n");
            }
        } else {
            printf("Could not Get kAudioConverterCompressionMagicCookie from Audio Converter!\n");
        }
        
		delete [] cookie;
	}
}
Exemplo n.º 3
0
void MyCopyEncoderCookieToFile(AudioQueueRef queue,
							AudioFileID theFile)
{
	OSStatus error;
	UInt32 propertySize;

	error = AudioQueueGetPropertySize(queue, kAudioConverterCompressionMagicCookie, &propertySize);

	if (error == noErr && propertySize > 0)
	{
		Byte *magicCookie = (Byte *)malloc(propertySize);
		CheckError(AudioQueueGetProperty(queue,
										kAudioQueueProperty_MagicCookie,
										magicCookie,
										&propertySize),
				"Couldn't get audio queue's magic cookie!");

		CheckError(AudioFileSetProperty(theFile,
										kAudioFilePropertyMagicCookieData,
										propertySize,
										magicCookie),
				"Couldn't set audio file's magic cookie");
		free(magicCookie);
	}
}
Exemplo n.º 4
0
// _______________________________________________________________________________________
//
void	CAAudioFile::FlushEncoder()
{
	if (mConverter != NULL) {
		mFinishingEncoding = true;
		WritePacketsFromCallback(WriteInputProc, this);
		mFinishingEncoding = false;

		// get priming info from converter, set it on the file
		if (mFileDataFormat.mBitsPerChannel == 0) {
			UInt32 propertySize;
			OSStatus err;
			AudioConverterPrimeInfo primeInfo;
			propertySize = sizeof(primeInfo);

			err = AudioConverterGetProperty(mConverter, kAudioConverterPrimeInfo, &propertySize, &primeInfo);
			if (err == noErr) {
				AudioFilePacketTableInfo pti;
				propertySize = sizeof(pti);
				err = AudioFileGetProperty(mAudioFile, kAudioFilePropertyPacketTableInfo, &propertySize, &pti);
				if (err == noErr) {
//printf("old packet table info: %qd valid, %ld priming, %ld remainder\n", pti.mNumberValidFrames, pti.mPrimingFrames, pti.mRemainderFrames);
					UInt64 totalFrames = pti.mNumberValidFrames + pti.mPrimingFrames + pti.mRemainderFrames;
					pti.mPrimingFrames = primeInfo.leadingFrames;
					pti.mRemainderFrames = primeInfo.trailingFrames;
					pti.mNumberValidFrames = totalFrames - pti.mPrimingFrames - pti.mRemainderFrames;
//printf("new packet table info: %qd valid, %ld priming, %ld remainder\n", pti.mNumberValidFrames, pti.mPrimingFrames, pti.mRemainderFrames);
					XThrowIfError(AudioFileSetProperty(mAudioFile, kAudioFilePropertyPacketTableInfo, sizeof(pti), &pti), "couldn't set packet table info on audio file");
				}
			}
		}
	}
}
Exemplo n.º 5
0
// ____________________________________________________________________________________
// Copy a queue's encoder's magic cookie to an audio file.
static void MyCopyEncoderCookieToFile(AudioQueueRef theQueue, AudioFileID theFile)
{
	OSStatus err;
	UInt32 propertySize;
	
	// get the magic cookie, if any, from the converter		
	err = AudioQueueGetPropertySize(theQueue, kAudioConverterCompressionMagicCookie, &propertySize);
	
	if (err == noErr && propertySize > 0) {
		// there is valid cookie data to be fetched;  get it
		Byte *magicCookie = (Byte *)malloc(propertySize);
		try {
			XThrowIfError(AudioQueueGetProperty(theQueue, kAudioConverterCompressionMagicCookie, magicCookie,
				&propertySize), "get audio converter's magic cookie");
			// now set the magic cookie on the output file
            // even though some formats have cookies, some files don't take them, so we ignore the error
			/*err =*/ AudioFileSetProperty(theFile, kAudioFilePropertyMagicCookieData, propertySize, magicCookie);
		} 
		catch (CAXException e) {
			char buf[256];
			fprintf(stderr, "MyCopyEncoderCookieToFile: %s (%s)\n", e.mOperation, e.FormatError(buf));
		}
        catch (...) {
            fprintf(stderr, "MyCopyEncoderCookieToFile: Unexpected exception\n");
        }
		free(magicCookie);
	}
}
Exemplo n.º 6
0
OSStatus SetMagicCookieForFile (
    AudioQueueRef inQueue,                                      // 1
    AudioFileID   inFile                                        // 2
) {
    OSStatus result = noErr;                                    // 3
    UInt32 cookieSize;                                          // 4
 
    if (
            AudioQueueGetPropertySize (                         // 5
                inQueue,
                kAudioQueueProperty_MagicCookie,
                &cookieSize
            ) == noErr
    ) {
        char* magicCookie =
            (char *) malloc (cookieSize);                       // 6
        if (
                AudioQueueGetProperty (                         // 7
                    inQueue,
                    kAudioQueueProperty_MagicCookie,
                    magicCookie,
                    &cookieSize
                ) == noErr
        )
            result =    AudioFileSetProperty (                  // 8
                            inFile,
                            kAudioFilePropertyMagicCookieData,
                            cookieSize,
                            magicCookie
                        );
        free (magicCookie);                                     // 9
    }
    return result;                                              // 10
}
Exemplo n.º 7
0
void	HLAudioFile::SetAudioFrameSize(SInt64 inSize)
{
	ThrowIf(mAudioFileID == 0, CAException(fnOpnErr), "HLAudioFile::SetAudioFrameSize: file isn't prepared");
	
	UInt32 theSize = sizeof(UInt64);
	UInt64 theFrameSize = inSize;
	OSStatus theError = AudioFileSetProperty(mAudioFileID, kAudioFilePropertyAudioDataPacketCount, theSize, &theFrameSize);
	ThrowIfError(theError, CAException(theError), "HLAudioFile::SetAudioFrameSize: couldn't set the property");
}
// Sets the packet table containing information about the number of valid frames in a file and where they begin and end
// for the file types that support this information.
// Calling this function makes sure we write out the priming and remainder details to the destination file	
static void WritePacketTableInfo(AudioConverterRef converter, AudioFileID destinationFileID)
{
    UInt32 isWritable;
    UInt32 dataSize;
    OSStatus error = AudioFileGetPropertyInfo(destinationFileID, kAudioFilePropertyPacketTableInfo, &dataSize, &isWritable);
    if (noErr == error && isWritable) {

        AudioConverterPrimeInfo primeInfo;
        dataSize = sizeof(primeInfo);

        // retrieve the leadingFrames and trailingFrames information from the converter,
        error = AudioConverterGetProperty(converter, kAudioConverterPrimeInfo, &dataSize, &primeInfo);
        if (noErr == error) {
            // we have some priming information to write out to the destination file
            /* The total number of packets in the file times the frames per packet (or counting each packet's
               frames individually for a variable frames per packet format) minus mPrimingFrames, minus
               mRemainderFrames, should equal mNumberValidFrames.
            */
            AudioFilePacketTableInfo pti;
            dataSize = sizeof(pti);
            error = AudioFileGetProperty(destinationFileID, kAudioFilePropertyPacketTableInfo, &dataSize, &pti);
            if (noErr == error) {
                // there's priming to write out to the file
                UInt64 totalFrames = pti.mNumberValidFrames + pti.mPrimingFrames + pti.mRemainderFrames; // get the total number of frames from the output file
                printf("Total number of frames from output file: %lld\n", totalFrames);
                
                pti.mPrimingFrames = primeInfo.leadingFrames;
                pti.mRemainderFrames = primeInfo.trailingFrames;
                pti.mNumberValidFrames = totalFrames - pti.mPrimingFrames - pti.mRemainderFrames;
            
                error = AudioFileSetProperty(destinationFileID, kAudioFilePropertyPacketTableInfo, sizeof(pti), &pti);
                if (noErr == error) {
                    printf("Writing packet table information to destination file: %ld\n", sizeof(pti));
                    printf("     Total valid frames: %lld\n", pti.mNumberValidFrames);
                    printf("         Priming frames: %ld\n", pti.mPrimingFrames);
                    printf("       Remainder frames: %ld\n", pti.mRemainderFrames);
                } else {
                    printf("Some audio files can't contain packet table information and that's OK\n");
                }
            } else {
                 printf("Getting kAudioFilePropertyPacketTableInfo error: %ld\n", error);
            }
        } else {
            printf("No kAudioConverterPrimeInfo available and that's OK\n");
        }
    } else {
        printf("GetPropertyInfo for kAudioFilePropertyPacketTableInfo error: %ld, isWritable: %ld\n", error, isWritable);
    }
}
Exemplo n.º 9
0
void SoundRecorder::setAudioFileMagicCookie(void)
	{
	/* Query the size of the magic cookie: */
	UInt32 magicCookieSize;
	if(AudioQueueGetPropertySize(queue,kAudioQueueProperty_MagicCookie,&magicCookieSize)==noErr)
		{
		/* Allocate a buffer for the magic cookie: */
		char* magicCookie=new char[magicCookieSize];
		
		/* Copy the magic cookie from the audio queue into the audio file: */
		if(AudioQueueGetProperty(queue,kAudioQueueProperty_MagicCookie,magicCookie,&magicCookieSize)==noErr)
			AudioFileSetProperty(audioFile,kAudioFilePropertyMagicCookieData,magicCookieSize,magicCookie);
		
		/* Delete the cookie buffer: */
		delete[] magicCookie;
		}
	}
Exemplo n.º 10
0
// ____________________________________________________________________________________
// Copy a queue's encoder's magic cookie to an audio file.
static void MyCopyEncoderCookieToFile(AudioQueueRef theQueue, AudioFileID theFile)
{
	OSStatus err;
	UInt32 propertySize;
	
	// get the magic cookie, if any, from the converter		
	err = AudioQueueGetPropertySize(theQueue, kAudioConverterCompressionMagicCookie, &propertySize);
	
	if (err == noErr && propertySize > 0) {
		// there is valid cookie data to be fetched;  get it
		Byte *magicCookie = (Byte *)malloc(propertySize);
		CheckError(AudioQueueGetProperty(theQueue, kAudioConverterCompressionMagicCookie, magicCookie,
			&propertySize), "get audio converter's magic cookie");
		// now set the magic cookie on the output file
		err = AudioFileSetProperty(theFile, kAudioFilePropertyMagicCookieData, propertySize, magicCookie);
		free(magicCookie);
	}
}
// Write output channel layout to destination file
static void WriteDestinationChannelLayout(AudioConverterRef converter, AudioFileID sourceFileID, AudioFileID destinationFileID)
{
    UInt32 layoutSize = 0;
    bool layoutFromConverter = true;
    
    OSStatus error = AudioConverterGetPropertyInfo(converter, kAudioConverterOutputChannelLayout, &layoutSize, NULL);
        
    // if the Audio Converter doesn't have a layout see if the input file does
    if (error || 0 == layoutSize) {
        error = AudioFileGetPropertyInfo(sourceFileID, kAudioFilePropertyChannelLayout, &layoutSize, NULL);
        layoutFromConverter = false;
    }
    
    if (noErr == error && 0 != layoutSize) {
        char* layout = new char[layoutSize];
        
        if (layoutFromConverter) {
            error = AudioConverterGetProperty(converter, kAudioConverterOutputChannelLayout, &layoutSize, layout);
            if (error) printf("Could not Get kAudioConverterOutputChannelLayout from Audio Converter!\n");
        } else {
            error = AudioFileGetProperty(sourceFileID, kAudioFilePropertyChannelLayout, &layoutSize, layout);
            if (error) printf("Could not Get kAudioFilePropertyChannelLayout from source file!\n");
        }
        
        if (noErr == error) {
            error = AudioFileSetProperty(destinationFileID, kAudioFilePropertyChannelLayout, layoutSize, layout);
            if (noErr == error) {
                printf("Writing channel layout to destination file: %ld\n", layoutSize);
            } else {
                printf("Even though some formats have layouts, some files don't take them and that's OK\n");
            }
        }
        
        delete [] layout;
    }
}
Exemplo n.º 12
0
// _______________________________________________________________________________________
//
void	CAAudioFile::SetNumberFrames(SInt64 nFrames)
{
	XThrowIf(mFileDataFormat.mFramesPerPacket != 1, kExtAudioFileError_InvalidDataFormat, "SetNumberFrames only supported for PCM");
	XThrowIfError(AudioFileSetProperty(mAudioFile, kAudioFilePropertyAudioDataPacketCount, sizeof(SInt64), &nFrames), "Couldn't set number of packets on audio file");
}
Exemplo n.º 13
0
// _______________________________________________________________________________________
//
// called to create the file -- or update its format/channel layout/properties based on an encoder
// setting change
void	CAAudioFile::FileFormatChanged(const FSRef *parentDir, CFStringRef filename, AudioFileTypeID filetype)
{
	LOG_FUNCTION("CAAudioFile::FileFormatChanged", "%p", this);
	XThrowIf(mMode != kPreparingToCreate && mMode != kPreparingToWrite, kExtAudioFileError_InvalidOperationOrder, "new file not prepared");

	UInt32 propertySize;
	OSStatus err;
	AudioStreamBasicDescription saveFileDataFormat = mFileDataFormat;

#if VERBOSE_CONVERTER
	mFileDataFormat.PrintFormat(stdout, "", "Specified file data format");
#endif

	// Find out the actual format the converter will produce. This is necessary in
	// case the bitrate has forced a lower sample rate, which needs to be set correctly
	// in the stream description passed to AudioFileCreate.
	if (mConverter != NULL) {
		propertySize = sizeof(AudioStreamBasicDescription);
		Float64 origSampleRate = mFileDataFormat.mSampleRate;
		XThrowIfError(AudioConverterGetProperty(mConverter, kAudioConverterCurrentOutputStreamDescription, &propertySize, &mFileDataFormat), "get audio converter's output stream description");
		// do the same for the channel layout being output by the converter
#if VERBOSE_CONVERTER
		mFileDataFormat.PrintFormat(stdout, "", "Converter output");
#endif
		if (fiszero(mFileDataFormat.mSampleRate))
			mFileDataFormat.mSampleRate = origSampleRate;
		err = AudioConverterGetPropertyInfo(mConverter, kAudioConverterOutputChannelLayout, &propertySize, NULL);
		if (err == noErr && propertySize > 0) {
			AudioChannelLayout *layout = static_cast<AudioChannelLayout *>(malloc(propertySize));
			err = AudioConverterGetProperty(mConverter, kAudioConverterOutputChannelLayout, &propertySize, layout);
			if (err) {
				free(layout);
				XThrow(err, "couldn't get audio converter's output channel layout");
			}
			mFileChannelLayout = layout;
#if VERBOSE_CHANNELMAP
			printf("got new file's channel layout from converter: %s\n", CAChannelLayouts::ConstantToString(mFileChannelLayout.Tag()));
#endif
			free(layout);
		}
	}

	// create the output file
	if (mMode == kPreparingToCreate) {
		CAStreamBasicDescription newFileDataFormat = mFileDataFormat;
		if (fiszero(newFileDataFormat.mSampleRate))
			newFileDataFormat.mSampleRate = 44100;	// just make something up for now
#if VERBOSE_CONVERTER
		newFileDataFormat.PrintFormat(stdout, "", "Applied to new file");
#endif
		XThrowIfError(AudioFileCreate(parentDir, filename, filetype, &newFileDataFormat, 0, &mFSRef, &mAudioFile), "create audio file");
		mMode = kPreparingToWrite;
		mOwnOpenFile = true;
	} else if (saveFileDataFormat != mFileDataFormat || fnotequal(saveFileDataFormat.mSampleRate, mFileDataFormat.mSampleRate)) {
		// second check must be explicit since operator== on ASBD treats SR of zero as "don't care"
		if (fiszero(mFileDataFormat.mSampleRate))
			mFileDataFormat.mSampleRate = mClientDataFormat.mSampleRate;
#if VERBOSE_CONVERTER
		mFileDataFormat.PrintFormat(stdout, "", "Applied to new file");
#endif
		XThrowIf(fiszero(mFileDataFormat.mSampleRate), kExtAudioFileError_InvalidDataFormat, "file's sample rate is 0");
		XThrowIfError(AudioFileSetProperty(mAudioFile, kAudioFilePropertyDataFormat, sizeof(AudioStreamBasicDescription), &mFileDataFormat), "couldn't update file's data format");
	}

	UInt32 deferSizeUpdates = 1;
	err = AudioFileSetProperty(mAudioFile, kAudioFilePropertyDeferSizeUpdates, sizeof(UInt32), &deferSizeUpdates);

	if (mConverter != NULL) {
		// encoder
		// get the magic cookie, if any, from the converter
		delete[] mMagicCookie;	mMagicCookie = NULL;
		mMagicCookieSize = 0;

		err = AudioConverterGetPropertyInfo(mConverter, kAudioConverterCompressionMagicCookie, &propertySize, NULL);

		// we can get a noErr result and also a propertySize == 0
		// -- if the file format does support magic cookies, but this file doesn't have one.
		if (err == noErr && propertySize > 0) {
			mMagicCookie = new Byte[propertySize];
			XThrowIfError(AudioConverterGetProperty(mConverter, kAudioConverterCompressionMagicCookie, &propertySize, mMagicCookie), "get audio converter's magic cookie");
			mMagicCookieSize = propertySize;	// the converter lies and tell us the wrong size
			// now set the magic cookie on the output file
			UInt32 willEatTheCookie = false;
			// the converter wants to give us one; will the file take it?
			err = AudioFileGetPropertyInfo(mAudioFile, kAudioFilePropertyMagicCookieData,
					NULL, &willEatTheCookie);
			if (err == noErr && willEatTheCookie) {
#if VERBOSE_CONVERTER
				printf("Setting cookie on encoded file\n");
#endif
				XThrowIfError(AudioFileSetProperty(mAudioFile, kAudioFilePropertyMagicCookieData, mMagicCookieSize, mMagicCookie), "set audio file's magic cookie");
			}
		}

		// get maximum packet size
		propertySize = sizeof(UInt32);
		XThrowIfError(AudioConverterGetProperty(mConverter, kAudioConverterPropertyMaximumOutputPacketSize, &propertySize, &mFileMaxPacketSize), "get audio converter's maximum output packet size");

		AllocateBuffers(true /* okToFail */);
	} else {
		InitFileMaxPacketSize();
	}

	if (mFileChannelLayout.IsValid() && mFileChannelLayout.NumberChannels() > 2) {
		// don't bother tagging mono/stereo files
		UInt32 isWritable;
		err = AudioFileGetPropertyInfo(mAudioFile, kAudioFilePropertyChannelLayout, NULL, &isWritable);
		if (!err && isWritable) {
#if VERBOSE_CHANNELMAP
			printf("writing file's channel layout: %s\n", CAChannelLayouts::ConstantToString(mFileChannelLayout.Tag()));
#endif
			err = AudioFileSetProperty(mAudioFile, kAudioFilePropertyChannelLayout,
				mFileChannelLayout.Size(), &mFileChannelLayout.Layout());
			if (err)
				CAXException::Warning("could not set the file's channel layout", err);
		} else {
#if VERBOSE_CHANNELMAP
			printf("file won't accept a channel layout (write)\n");
#endif
		}
	}

	UpdateClientMaxPacketSize();	// also sets mFrame0Offset
	mPacketMark = 0;
	mFrameMark = 0;
}