Ejemplo n.º 1
0
int32_t setup_queue(
	ALACMagicCookie cookie,
	PlayerInfo *playerInfo,
	uint32_t buffer_size,
	uint32_t num_buffers,
	uint32_t num_packets
) {
  // Create Audio Queue for ALAC
  AudioStreamBasicDescription inFormat = {0};
  inFormat.mSampleRate = ntohl(cookie.sampleRate);
  inFormat.mFormatID = kAudioFormatAppleLossless;
  inFormat.mFormatFlags = 0; // ALAC uses no flags
  inFormat.mBytesPerPacket = 0; // Variable size (must use AudioStreamPacketDescription)
  inFormat.mFramesPerPacket = ntohl(cookie.frameLength);
  inFormat.mBytesPerFrame = 0; // Compressed
  inFormat.mChannelsPerFrame = 2; // Stero TODO: get from fmtp?
  inFormat.mBitsPerChannel = 0; // Compressed
  inFormat.mReserved = 0;

  OSStatus err = AudioQueueNewOutput(
      &inFormat,
      c_callback,
      playerInfo, // User data
      NULL, // Run on audio queue's thread
      NULL, // Callback run loop's mode
      0, // Reserved
      &playerInfo->queue);

  if (err) return err;

  // Need to set the magic cookie too (tail fmtp)
  err = AudioQueueSetProperty(playerInfo->queue, kAudioQueueProperty_MagicCookie,
			&cookie, sizeof(ALACMagicCookie));
  if (err) return err;

	// Create input buffers, and enqueue using callback
	for (int i = 0; i < num_buffers; i++) {
		AudioQueueBufferRef buffer;
		err = AudioQueueAllocateBufferWithPacketDescriptions(
				playerInfo->queue, buffer_size, num_packets, &buffer);
		if (err) return err;

		c_callback(playerInfo, playerInfo->queue, buffer);
	}

	// Volume full
	err = AudioQueueSetParameter(playerInfo->queue, kAudioQueueParam_Volume, 1.0);
	if (err) return err;

  // Prime
  err = AudioQueuePrime(playerInfo->queue, 0, NULL);
  if (err) return err;

	// Start
	err = AudioQueueStart(playerInfo->queue, NULL);
	if (err) return err;

	return 0;
}
void AudioStreamDecoder::PropertyCallback(AudioFileStreamID stream, AudioFileStreamPropertyID property, UInt32* flags)
{
	if (property != kAudioFileStreamProperty_ReadyToProducePackets)
		return;

	long err;
	void* buffer = NULL;
	unsigned char writable;
	AudioStreamBasicDescription desc = {0};
	UInt32 size = sizeof(desc);

	BAIL_IF(!stream || stream != mStream, "Invalid stream %p\n", stream);

	err = AudioFileStreamGetProperty(mStream, kAudioFileStreamProperty_DataFormat, &size, &desc);
	BAIL_IF(err, "AudioFileStreamGetProperty returned %ld\n", err);

	err = AudioQueueNewOutput(&desc, StaticBufferCompleteCallback, this, NULL, NULL, 0, &mQueue);
	BAIL_IF(err, "AudioQueueNewOutput returned %ld\n", err);

	err = AudioQueueAddPropertyListener(mQueue, kAudioQueueProperty_IsRunning, StaticQueueRunningCallback, this);
	BAIL_IF(err, "AudioQueueAddPropertyListener returned %ld\n", err);

	for (int i = 0; i < kBufferCount; i++)
	{
		err = AudioQueueAllocateBufferWithPacketDescriptions(mQueue, kBufferSize, kBufferPacketDescs, mBuffers + i);
		BAIL_IF(err, "AudioQueueAllocateBuffer returned %ld\n", err);
	}

	mCurrentBuffer = mBuffers;
	(*mCurrentBuffer)->mUserData = this;

	err = AudioFileStreamGetPropertyInfo(mStream, kAudioFileStreamProperty_MagicCookieData, &size, &writable);
	BAIL_IF(err, "AudioFileStreamGetPropertyInfo returned %ld\n", err);

	buffer = malloc(size);
	BAIL_IF(!buffer, "Failed to allocate %u byte buffer for cookie\n", (unsigned int)size);

	err = AudioFileStreamGetProperty(mStream, kAudioFileStreamProperty_MagicCookieData, &size, buffer);
	BAIL_IF(err, "AudioFileStreamGetProperty returned %ld\n", err);

	err = AudioQueueSetProperty(mQueue, kAudioQueueProperty_MagicCookie, buffer, size);
	BAIL_IF(err, "AudioQueueSetProperty returned %ld\n", err);

bail:
	free(buffer);
}
Ejemplo n.º 3
0
Archivo: play.c Proyecto: jonahb/play
int main (int argc, const char *argv[])
{
    OSStatus result;
    State *state = NULL;

    if (argc != 2) {
        printf("Usage: play <file>\n");
        goto error;
    }


    state = StateCreate();


    //
    // open the audio file
    //

    CFURLRef fileURL = CFURLCreateFromFileSystemRepresentation(
        kCFAllocatorDefault,
        (const UInt8*)argv[1],
        strlen(argv[1]),
        false
    );

    if (!fileURL) {
        Error("Invalid filename");
        goto error;
    }

    result = AudioFileOpenURL(
        fileURL,
        kAudioFileReadPermission,
        0,
        &state->audioFile
    );

    CFRelease(fileURL);

    if (result) {
        Error("Invalid audio file");
        goto error;
    }


    //
    // determine properties of stream including maximum packet size
    //

    UInt32 propertyDataSize;

    AudioStreamBasicDescription streamDescription;
    propertyDataSize = sizeof(streamDescription);

    result = AudioFileGetProperty(
        state->audioFile,
        kAudioFilePropertyDataFormat,
        &propertyDataSize,
        &streamDescription
    );

    if (result) {
        Error(NULL);
        goto error;
    }

    UInt32 maximumPacketSize;
    propertyDataSize = sizeof(maximumPacketSize);

    result = AudioFileGetProperty(
        state->audioFile,
        kAudioFilePropertyMaximumPacketSize,
        &propertyDataSize,
        &maximumPacketSize
    );

    if (result) {
        Error(NULL);
        goto error;
    }


    //
    // initialize the audio queue and allocate buffers
    //

    result = AudioQueueNewOutput(
        &streamDescription,
        AudioQueueOutput,
        state,
        CFRunLoopGetCurrent(),
        kCFRunLoopDefaultMode,
        0,
        &state->audioQueue
    );

    if (result) {
        Error("Failed to initialize audio queue");
        goto error;
    }

    state->audioBufferSize = maximumPacketSize * PACKETS_PER_BUFFER;

    AudioQueueBufferRef audioQueueBuffers[NUM_BUFFERS];

    for (int i = 0; i < NUM_BUFFERS; ++i)
    {
        result = AudioQueueAllocateBufferWithPacketDescriptions(
            state->audioQueue,
            state->audioBufferSize,
            PACKETS_PER_BUFFER,
            &audioQueueBuffers[i]
        );

        if (result) {
            Error("Failed to initialize audio queue buffer");
            goto error;
        }
    }

    result = AudioQueueAddPropertyListener(
        state->audioQueue,
        kAudioQueueProperty_IsRunning,
        AudioQueuePropertyListener,
        NULL
    );


    //
    // prime and start the audio queue
    //

    AudioQueueOutput(
        state,
        state->audioQueue,
        audioQueueBuffers[0]
    );

    result = AudioQueueStart(
        state->audioQueue,
        NULL
    );

    if (result) {
        Error("Failed to start audio queue");
        goto error;
    }


    //
    // start the run loop that will dispatch audio queue callbacks
    //

    CFRunLoopRun();

    StateDestroy(state);

    return 0;

error:

    if (state) {
        StateDestroy(state);
    }

    return 1;
}