コード例 #1
0
ファイル: mac-audio.c プロジェクト: rtjason/obs-studio
static bool coreaudio_init_format(struct coreaudio_data *ca)
{
	AudioStreamBasicDescription desc;
	OSStatus stat;
	UInt32 size = sizeof(desc);

	stat = get_property(ca->unit, kAudioUnitProperty_StreamFormat,
			SCOPE_INPUT, BUS_INPUT, &desc, &size);
	if (!ca_success(stat, ca, "coreaudio_init_format", "get input format"))
		return false;

	/* Certain types of devices have no limit on channel count, and
	 * there's no way to know the actual number of channels it's using,
	 * so if we encounter this situation just force to stereo */
        if (desc.mChannelsPerFrame > 8) {
                desc.mChannelsPerFrame = 2;
                desc.mBytesPerFrame = 2 * desc.mBitsPerChannel / 8;
                desc.mBytesPerPacket =
                        desc.mFramesPerPacket * desc.mBytesPerFrame;
        }

	stat = set_property(ca->unit, kAudioUnitProperty_StreamFormat,
			SCOPE_OUTPUT, BUS_INPUT, &desc, size);
	if (!ca_success(stat, ca, "coreaudio_init_format", "set output format"))
		return false;

	if (desc.mFormatID != kAudioFormatLinearPCM) {
		ca_warn(ca, "coreaudio_init_format", "format is not PCM");
		return false;
	}

	ca->format = convert_ca_format(desc.mFormatFlags, desc.mBitsPerChannel);
	if (ca->format == AUDIO_FORMAT_UNKNOWN) {
		ca_warn(ca, "coreaudio_init_format", "unknown format flags: "
				"%u, bits: %u",
				(unsigned int)desc.mFormatFlags,
				(unsigned int)desc.mBitsPerChannel);
		return false;
	}

	ca->sample_rate = (uint32_t)desc.mSampleRate;
	ca->speakers = convert_ca_speaker_layout(desc.mChannelsPerFrame);

	if (ca->speakers == SPEAKERS_UNKNOWN) {
		ca_warn(ca, "coreaudio_init_format", "unknown speaker layout: "
				"%u channels",
				(unsigned int)desc.mChannelsPerFrame);
		return false;
	}

	return true;
}
コード例 #2
0
ファイル: mac-audio.c プロジェクト: CuylarStudios/obs-studio
static OSStatus input_callback(
		void *data,
		AudioUnitRenderActionFlags *action_flags,
		const AudioTimeStamp *ts_data,
		UInt32 bus_num,
		UInt32 frames,
		AudioBufferList *ignored_buffers)
{
	struct coreaudio_data *ca = data;
	OSStatus stat;
	struct source_audio audio;

	stat = AudioUnitRender(ca->unit, action_flags, ts_data, bus_num, frames,
			ca->buf_list);
	if (!ca_success(stat, ca, "input_callback", "audio retrieval"))
		return noErr;

	for (UInt32 i = 0; i < ca->buf_list->mNumberBuffers; i++)
		audio.data[i] = ca->buf_list->mBuffers[i].mData;

	audio.frames          = frames;
	audio.speakers        = ca->speakers;
	audio.format          = ca->format;
	audio.samples_per_sec = ca->sample_rate;
	audio.timestamp       = ts_data->mHostTime;

	obs_source_output_audio(ca->source, &audio);

	UNUSED_PARAMETER(ignored_buffers);
	return noErr;
}
コード例 #3
0
ファイル: mac-audio.c プロジェクト: CuylarStudios/obs-studio
static bool coreaudio_init_buffer(struct coreaudio_data *ca)
{
	UInt32 buf_size = 0;
	UInt32 size     = 0;
	UInt32 frames   = 0;
	OSStatus stat;

	AudioObjectPropertyAddress addr = {
		kAudioDevicePropertyStreamConfiguration,
		kAudioDevicePropertyScopeInput,
		kAudioObjectPropertyElementMaster
	};

	stat = AudioObjectGetPropertyDataSize(ca->device_id, &addr, 0, NULL,
			&buf_size);
	if (!ca_success(stat, ca, "coreaudio_init_buffer", "get list size"))
		return false;

	size = sizeof(frames);
	stat = get_property(ca->unit, kAudioDevicePropertyBufferFrameSize,
			SCOPE_GLOBAL, 0, &frames, &size);
	if (!ca_success(stat, ca, "coreaudio_init_buffer", "get frame size"))
		return false;

	/* ---------------------- */

	ca->buf_list = bmalloc(buf_size);

	stat = AudioObjectGetPropertyData(ca->device_id, &addr, 0, NULL,
			&buf_size, ca->buf_list);
	if (!ca_success(stat, ca, "coreaudio_init_buffer", "allocate")) {
		bfree(ca->buf_list);
		ca->buf_list = NULL;
		return false;
	}

	for (UInt32 i = 0; i < ca->buf_list->mNumberBuffers; i++) {
		size = ca->buf_list->mBuffers[i].mDataByteSize;
		ca->buf_list->mBuffers[i].mData = bmalloc(size);
	}
	
	return true;
}
コード例 #4
0
ファイル: mac-audio.c プロジェクト: CuylarStudios/obs-studio
static bool coreaudio_init_format(struct coreaudio_data *ca)
{
	AudioStreamBasicDescription desc;
	OSStatus stat;
	UInt32 size = sizeof(desc);

	stat = get_property(ca->unit, kAudioUnitProperty_StreamFormat,
			SCOPE_INPUT, BUS_INPUT, &desc, &size);
	if (!ca_success(stat, ca, "coreaudio_init_format", "get input format"))
		return false;

	stat = set_property(ca->unit, kAudioUnitProperty_StreamFormat,
			SCOPE_OUTPUT, BUS_INPUT, &desc, size);
	if (!ca_success(stat, ca, "coreaudio_init_format", "set output format"))
		return false;

	if (desc.mFormatID != kAudioFormatLinearPCM) {
		ca_warn(ca, "coreaudio_init_format", "format is not PCM");
		return false;
	}

	ca->format = convert_ca_format(desc.mFormatFlags, desc.mBitsPerChannel);
	if (ca->format == AUDIO_FORMAT_UNKNOWN) {
		ca_warn(ca, "coreaudio_init_format", "unknown format flags: "
				"%u, bits: %u",
				(unsigned int)desc.mFormatFlags,
				(unsigned int)desc.mBitsPerChannel);
		return false;
	}

	ca->sample_rate = (uint32_t)desc.mSampleRate;
	ca->speakers = convert_ca_speaker_layout(desc.mChannelsPerFrame);

	if (ca->speakers == SPEAKERS_UNKNOWN) {
		ca_warn(ca, "coreaudio_init_format", "unknown speaker layout: "
				"%u channels",
				(unsigned int)desc.mChannelsPerFrame);
		return false;
	}

	return true;
}
コード例 #5
0
ファイル: mac-audio.c プロジェクト: CuylarStudios/obs-studio
static bool coreaudio_init_hooks(struct coreaudio_data *ca)
{
	OSStatus stat;
	AURenderCallbackStruct callback_info = {
		.inputProc       = input_callback,
		.inputProcRefCon = ca
	};

	stat = add_listener(ca, kAudioDevicePropertyDeviceIsAlive);
	if (!ca_success(stat, ca, "coreaudio_init_hooks",
				"set disconnect callback"))
		return false;

	stat = add_listener(ca, PROPERTY_FORMATS);
	if (!ca_success(stat, ca, "coreaudio_init_hooks",
				"set format change callback"))
		return false;

	if (ca->default_device) {
		AudioObjectPropertyAddress addr = {
			PROPERTY_DEFAULT_DEVICE,
			kAudioObjectPropertyScopeGlobal,
			kAudioObjectPropertyElementMaster
		};

		stat = AudioObjectAddPropertyListener(kAudioObjectSystemObject,
				&addr, notification_callback, ca);
		if (!ca_success(stat, ca, "coreaudio_init_hooks",
					"set device change callback"))
			return false;
	}

	stat = set_property(ca->unit, kAudioOutputUnitProperty_SetInputCallback,
			SCOPE_GLOBAL, 0, &callback_info, sizeof(callback_info));
	if (!ca_success(stat, ca, "coreaudio_init_hooks", "set input callback"))
		return false;

	return true;
}