Ejemplo n.º 1
1
bool audio::orchestra::api::Core::open(uint32_t _device,
                                       audio::orchestra::mode _mode,
                                       uint32_t _channels,
                                       uint32_t _firstChannel,
                                       uint32_t _sampleRate,
                                       audio::format _format,
                                       uint32_t *_bufferSize,
                                       const audio::orchestra::StreamOptions& _options) {
	// Get device ID
	uint32_t nDevices = getDeviceCount();
	if (nDevices == 0) {
		// This should not happen because a check is made before this function is called.
		ATA_ERROR("no devices found!");
		return false;
	}
	if (_device >= nDevices) {
		// This should not happen because a check is made before this function is called.
		ATA_ERROR("device ID is invalid!");
		return false;
	}
	AudioDeviceID deviceList[ nDevices/2 ];
	uint32_t dataSize = sizeof(AudioDeviceID) * nDevices/2;
	AudioObjectPropertyAddress property = {
		kAudioHardwarePropertyDevices,
		kAudioObjectPropertyScopeGlobal,
		kAudioObjectPropertyElementMaster
	};
	OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
	                                             &property,
	                                             0,
	                                             nullptr,
	                                             &dataSize,
	                                             (void *) &deviceList);
	if (result != noErr) {
		ATA_ERROR("OS-X system error getting device IDs.");
		return false;
	}
	AudioDeviceID id = deviceList[ _device/2 ];
	// Setup for stream mode.
	bool isInput = false;
	if (_mode == audio::orchestra::mode_input) {
		isInput = true;
		property.mScope = kAudioDevicePropertyScopeInput;
	} else {
		property.mScope = kAudioDevicePropertyScopeOutput;
	}
	// Get the stream "configuration".
	AudioBufferList	*bufferList = nil;
	dataSize = 0;
	property.mSelector = kAudioDevicePropertyStreamConfiguration;
	result = AudioObjectGetPropertyDataSize(id, &property, 0, nullptr, &dataSize);
	if (    result != noErr
	     || dataSize == 0) {
		ATA_ERROR("system error (" << getErrorCode(result) << ") getting stream configuration info for device (" << _device << ").");
		return false;
	}
	// Allocate the AudioBufferList.
	bufferList = (AudioBufferList *) malloc(dataSize);
	if (bufferList == nullptr) {
		ATA_ERROR("memory error allocating AudioBufferList.");
		return false;
	}
	result = AudioObjectGetPropertyData(id, &property, 0, nullptr, &dataSize, bufferList);
	if (    result != noErr
	     || dataSize == 0) {
		ATA_ERROR("system error (" << getErrorCode(result) << ") getting stream configuration for device (" << _device << ").");
		return false;
	}
	// Search for one or more streams that contain the desired number of
	// channels. CoreAudio devices can have an arbitrary number of
	// streams and each stream can have an arbitrary number of channels.
	// For each stream, a single buffer of interleaved samples is
	// provided. orchestra prefers the use of one stream of interleaved
	// data or multiple consecutive single-channel streams.	However, we
	// now support multiple consecutive multi-channel streams of
	// interleaved data as well.
	uint32_t iStream, offsetCounter = _firstChannel;
	uint32_t nStreams = bufferList->mNumberBuffers;
	bool monoMode = false;
	bool foundStream = false;
	// First check that the device supports the requested number of
	// channels.
	uint32_t deviceChannels = 0;
	for (iStream=0; iStream<nStreams; iStream++) {
		deviceChannels += bufferList->mBuffers[iStream].mNumberChannels;
	}
	if (deviceChannels < (_channels + _firstChannel)) {
		free(bufferList);
		ATA_ERROR("the device (" << _device << ") does not support the requested channel count.");
		return false;
	}
	// Look for a single stream meeting our needs.
	uint32_t firstStream, streamCount = 1, streamChannels = 0, channelOffset = 0;
	for (iStream=0; iStream<nStreams; iStream++) {
		streamChannels = bufferList->mBuffers[iStream].mNumberChannels;
		if (streamChannels >= _channels + offsetCounter) {
			firstStream = iStream;
			channelOffset = offsetCounter;
			foundStream = true;
			break;
		}
		if (streamChannels > offsetCounter) {
			break;
		}
		offsetCounter -= streamChannels;
	}
	// If we didn't find a single stream above, then we should be able
	// to meet the channel specification with multiple streams.
	if (foundStream == false) {
		monoMode = true;
		offsetCounter = _firstChannel;
		for (iStream=0; iStream<nStreams; iStream++) {
			streamChannels = bufferList->mBuffers[iStream].mNumberChannels;
			if (streamChannels > offsetCounter) {
				break;
			}
			offsetCounter -= streamChannels;
		}
		firstStream = iStream;
		channelOffset = offsetCounter;
		int32_t channelCounter = _channels + offsetCounter - streamChannels;
		if (streamChannels > 1) {
			monoMode = false;
		}
		while (channelCounter > 0) {
			streamChannels = bufferList->mBuffers[++iStream].mNumberChannels;
			if (streamChannels > 1) {
				monoMode = false;
			}
			channelCounter -= streamChannels;
			streamCount++;
		}
	}
	free(bufferList);
	// Determine the buffer size.
	AudioValueRange	bufferRange;
	dataSize = sizeof(AudioValueRange);
	property.mSelector = kAudioDevicePropertyBufferFrameSizeRange;
	result = AudioObjectGetPropertyData(id, &property, 0, nullptr, &dataSize, &bufferRange);
	if (result != noErr) {
		ATA_ERROR("system error (" << getErrorCode(result) << ") getting buffer size range for device (" << _device << ").");
		return false;
	}
	if (bufferRange.mMinimum > *_bufferSize) {
		*_bufferSize = (uint64_t) bufferRange.mMinimum;
	} else if (bufferRange.mMaximum < *_bufferSize) {
		*_bufferSize = (uint64_t) bufferRange.mMaximum;
	}
	if (_options.flags.m_minimizeLatency == true) {
		*_bufferSize = (uint64_t) bufferRange.mMinimum;
	}
	// Set the buffer size.	For multiple streams, I'm assuming we only
	// need to make this setting for the master channel.
	uint32_t theSize = (uint32_t) *_bufferSize;
	dataSize = sizeof(uint32_t);
	property.mSelector = kAudioDevicePropertyBufferFrameSize;
	result = AudioObjectSetPropertyData(id, &property, 0, nullptr, dataSize, &theSize);
	if (result != noErr) {
		ATA_ERROR("system error (" << getErrorCode(result) << ") setting the buffer size for device (" << _device << ").");
		return false;
	}
	// If attempting to setup a duplex stream, the bufferSize parameter
	// MUST be the same in both directions!
	*_bufferSize = theSize;
	if (    m_mode == audio::orchestra::mode_output
	     && _mode == audio::orchestra::mode_input
	     && *_bufferSize != m_bufferSize) {
		ATA_ERROR("system error setting buffer size for duplex stream on device (" << _device << ").");
		return false;
	}
	m_bufferSize = *_bufferSize;
	m_nBuffers = 1;
	// Check and if necessary, change the sample rate for the device.
	double nominalRate;
	dataSize = sizeof(double);
	property.mSelector = kAudioDevicePropertyNominalSampleRate;
	result = AudioObjectGetPropertyData(id, &property, 0, nullptr, &dataSize, &nominalRate);
	if (result != noErr) {
		ATA_ERROR("system error (" << getErrorCode(result) << ") getting current sample rate.");
		return false;
	}
	// Only change the sample rate if off by more than 1 Hz.
	if (fabs(nominalRate - (double)_sampleRate) > 1.0) {
		// Set a property listener for the sample rate change
		double reportedRate = 0.0;
		AudioObjectPropertyAddress tmp = { kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
		result = AudioObjectAddPropertyListener(id, &tmp, &rateListener, (void *) &reportedRate);
		if (result != noErr) {
			ATA_ERROR("system error (" << getErrorCode(result) << ") setting sample rate property listener for device (" << _device << ").");
			return false;
		}
		nominalRate = (double) _sampleRate;
		result = AudioObjectSetPropertyData(id, &property, 0, nullptr, dataSize, &nominalRate);
		if (result != noErr) {
			ATA_ERROR("system error (" << getErrorCode(result) << ") setting sample rate for device (" << _device << ").");
			return false;
		}
		// Now wait until the reported nominal rate is what we just set.
		uint32_t microCounter = 0;
		while (reportedRate != nominalRate) {
			microCounter += 5000;
			if (microCounter > 5000000) {
				break;
			}
			std::this_thread::sleep_for(std::chrono::milliseconds(5));
		}
		// Remove the property listener.
		AudioObjectRemovePropertyListener(id, &tmp, &rateListener, (void *) &reportedRate);
		if (microCounter > 5000000) {
			ATA_ERROR("timeout waiting for sample rate update for device (" << _device << ").");
			return false;
		}
	}
	// Now set the stream format for all streams.	Also, check the
	// physical format of the device and change that if necessary.
	AudioStreamBasicDescription	description;
	dataSize = sizeof(AudioStreamBasicDescription);
	property.mSelector = kAudioStreamPropertyVirtualFormat;
	result = AudioObjectGetPropertyData(id, &property, 0, nullptr, &dataSize, &description);
	if (result != noErr) {
		ATA_ERROR("system error (" << getErrorCode(result) << ") getting stream format for device (" << _device << ").");
		return false;
	}
	// Set the sample rate and data format id.	However, only make the
	// change if the sample rate is not within 1.0 of the desired
	// rate and the format is not linear pcm.
	bool updateFormat = false;
	if (fabs(description.mSampleRate - (double)_sampleRate) > 1.0) {
		description.mSampleRate = (double) _sampleRate;
		updateFormat = true;
	}
	if (description.mFormatID != kAudioFormatLinearPCM) {
		description.mFormatID = kAudioFormatLinearPCM;
		updateFormat = true;
	}
	if (updateFormat) {
		result = AudioObjectSetPropertyData(id, &property, 0, nullptr, dataSize, &description);
		if (result != noErr) {
			ATA_ERROR("system error (" << getErrorCode(result) << ") setting sample rate or data format for device (" << _device << ").");
			return false;
		}
	}
	// Now check the physical format.
	property.mSelector = kAudioStreamPropertyPhysicalFormat;
	result = AudioObjectGetPropertyData(id, &property, 0, nullptr,	&dataSize, &description);
	if (result != noErr) {
		ATA_ERROR("system error (" << getErrorCode(result) << ") getting stream physical format for device (" << _device << ").");
		return false;
	}
	//std::cout << "Current physical stream format:" << std::endl;
	//std::cout << "	 mBitsPerChan = " << description.mBitsPerChannel << std::endl;
	//std::cout << "	 aligned high = " << (description.mFormatFlags & kAudioFormatFlagIsAlignedHigh) << ", isPacked = " << (description.mFormatFlags & kAudioFormatFlagIsPacked) << std::endl;
	//std::cout << "	 bytesPerFrame = " << description.mBytesPerFrame << std::endl;
	//std::cout << "	 sample rate = " << description.mSampleRate << std::endl;
	if (    description.mFormatID != kAudioFormatLinearPCM
	     || description.mBitsPerChannel < 16) {
		description.mFormatID = kAudioFormatLinearPCM;
		//description.mSampleRate = (double) sampleRate;
		AudioStreamBasicDescription	testDescription = description;
		uint32_t formatFlags;
		// We'll try higher bit rates first and then work our way down.
		std::vector< std::pair<uint32_t, uint32_t>	> physicalFormats;
		formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsFloat) & ~kLinearPCMFormatFlagIsSignedInteger;
		physicalFormats.push_back(std::pair<float, uint32_t>(32, formatFlags));
		formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked) & ~kLinearPCMFormatFlagIsFloat;
		physicalFormats.push_back(std::pair<float, uint32_t>(32, formatFlags));
		physicalFormats.push_back(std::pair<float, uint32_t>(24, formatFlags));	 // 24-bit packed
		formatFlags &= ~(kAudioFormatFlagIsPacked | kAudioFormatFlagIsAlignedHigh);
		physicalFormats.push_back(std::pair<float, uint32_t>(24.2, formatFlags)); // 24-bit in 4 bytes, aligned low
		formatFlags |= kAudioFormatFlagIsAlignedHigh;
		physicalFormats.push_back(std::pair<float, uint32_t>(24.4, formatFlags)); // 24-bit in 4 bytes, aligned high
		formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked) & ~kLinearPCMFormatFlagIsFloat;
		physicalFormats.push_back(std::pair<float, uint32_t>(16, formatFlags));
		physicalFormats.push_back(std::pair<float, uint32_t>(8, formatFlags));
		bool setPhysicalFormat = false;
		for(uint32_t i=0; i<physicalFormats.size(); i++) {
			testDescription = description;
			testDescription.mBitsPerChannel = (uint32_t) physicalFormats[i].first;
			testDescription.mFormatFlags = physicalFormats[i].second;
			if (    (24 == (uint32_t)physicalFormats[i].first)
			     && ~(physicalFormats[i].second & kAudioFormatFlagIsPacked)) {
				testDescription.mBytesPerFrame =	4 * testDescription.mChannelsPerFrame;
			} else {
				testDescription.mBytesPerFrame =	testDescription.mBitsPerChannel/8 * testDescription.mChannelsPerFrame;
			}
			testDescription.mBytesPerPacket = testDescription.mBytesPerFrame * testDescription.mFramesPerPacket;
			result = AudioObjectSetPropertyData(id, &property, 0, nullptr, dataSize, &testDescription);
			if (result == noErr) {
				setPhysicalFormat = true;
				//std::cout << "Updated physical stream format:" << std::endl;
				//std::cout << "	 mBitsPerChan = " << testDescription.mBitsPerChannel << std::endl;
				//std::cout << "	 aligned high = " << (testDescription.mFormatFlags & kAudioFormatFlagIsAlignedHigh) << ", isPacked = " << (testDescription.mFormatFlags & kAudioFormatFlagIsPacked) << std::endl;
				//std::cout << "	 bytesPerFrame = " << testDescription.mBytesPerFrame << std::endl;
				//std::cout << "	 sample rate = " << testDescription.mSampleRate << std::endl;
				break;
			}
		}
		if (!setPhysicalFormat) {
			ATA_ERROR("system error (" << getErrorCode(result) << ") setting physical data format for device (" << _device << ").");
			return false;
		}
	} // done setting virtual/physical formats.
	// Get the stream / device latency.
	uint32_t latency;
	dataSize = sizeof(uint32_t);
	property.mSelector = kAudioDevicePropertyLatency;
	if (AudioObjectHasProperty(id, &property) == true) {
		result = AudioObjectGetPropertyData(id, &property, 0, nullptr, &dataSize, &latency);
		if (result == kAudioHardwareNoError) {
			m_latency[ _mode ] = latency;
		} else {
			ATA_ERROR("system error (" << getErrorCode(result) << ") getting device latency for device (" << _device << ").");
			return false;
		}
	}
	// Byte-swapping: According to AudioHardware.h, the stream data will
	// always be presented in native-endian format, so we should never
	// need to byte swap.
	m_doByteSwap[modeToIdTable(_mode)] = false;
	// From the CoreAudio documentation, PCM data must be supplied as
	// 32-bit floats.
	m_userFormat = _format;
	m_deviceFormat[modeToIdTable(_mode)] = audio::format_float;
	if (streamCount == 1) {
		m_nDeviceChannels[modeToIdTable(_mode)] = description.mChannelsPerFrame;
	} else {
		// multiple streams
		m_nDeviceChannels[modeToIdTable(_mode)] = _channels;
	}
	m_nUserChannels[modeToIdTable(_mode)] = _channels;
	m_channelOffset[modeToIdTable(_mode)] = channelOffset;	// offset within a CoreAudio stream
	m_deviceInterleaved[modeToIdTable(_mode)] = true;
	if (monoMode == true) {
		m_deviceInterleaved[modeToIdTable(_mode)] = false;
	}
	// Set flags for buffer conversion.
	m_doConvertBuffer[modeToIdTable(_mode)] = false;
	if (m_userFormat != m_deviceFormat[modeToIdTable(_mode)]) {
		m_doConvertBuffer[modeToIdTable(_mode)] = true;
	}
	if (m_nUserChannels[modeToIdTable(_mode)] < m_nDeviceChannels[modeToIdTable(_mode)]) {
		m_doConvertBuffer[modeToIdTable(_mode)] = true;
	}
	if (streamCount == 1) {
		if (    m_nUserChannels[modeToIdTable(_mode)] > 1
		     && m_deviceInterleaved[modeToIdTable(_mode)] == false) {
			m_doConvertBuffer[modeToIdTable(_mode)] = true;
		}
	} else if (monoMode) {
		m_doConvertBuffer[modeToIdTable(_mode)] = true;
	}
	m_private->iStream[modeToIdTable(_mode)] = firstStream;
	m_private->nStreams[modeToIdTable(_mode)] = streamCount;
	m_private->id[modeToIdTable(_mode)] = id;
	// Allocate necessary internal buffers.
	uint64_t bufferBytes;
	bufferBytes = m_nUserChannels[modeToIdTable(_mode)] * *_bufferSize * audio::getFormatBytes(m_userFormat);
	//	m_userBuffer[modeToIdTable(_mode)] = (char *) calloc(bufferBytes, 1);
	m_userBuffer[modeToIdTable(_mode)].resize(bufferBytes, 0);
	if (m_userBuffer[modeToIdTable(_mode)].size() == 0) {
		ATA_ERROR("error allocating user buffer memory.");
		goto error;
	}
	// If possible, we will make use of the CoreAudio stream buffers as
	// "device buffers".	However, we can't do this if using multiple
	// streams.
	if (    m_doConvertBuffer[modeToIdTable(_mode)]
	     && m_private->nStreams[modeToIdTable(_mode)] > 1) {
		bool makeBuffer = true;
		bufferBytes = m_nDeviceChannels[modeToIdTable(_mode)] * audio::getFormatBytes(m_deviceFormat[modeToIdTable(_mode)]);
		if (_mode == audio::orchestra::mode_input) {
			if (    m_mode == audio::orchestra::mode_output
			     && m_deviceBuffer) {
				uint64_t bytesOut = m_nDeviceChannels[0] * audio::getFormatBytes(m_deviceFormat[0]);
				if (bufferBytes <= bytesOut) {
					makeBuffer = false;
				}
			}
		}
		if (makeBuffer) {
			bufferBytes *= *_bufferSize;
			if (m_deviceBuffer) {
				free(m_deviceBuffer);
				m_deviceBuffer = nullptr;
			}
			m_deviceBuffer = (char *) calloc(bufferBytes, 1);
			if (m_deviceBuffer == nullptr) {
				ATA_ERROR("error allocating device buffer memory.");
				goto error;
			}
		}
	}
	m_sampleRate = _sampleRate;
	m_device[modeToIdTable(_mode)] = _device;
	m_state = audio::orchestra::state::stopped;
	ATA_VERBOSE("Set state as stopped");
	// Setup the buffer conversion information structure.
	if (m_doConvertBuffer[modeToIdTable(_mode)]) {
		if (streamCount > 1) {
			setConvertInfo(_mode, 0);
		} else {
			setConvertInfo(_mode, channelOffset);
		}
	}
	if (    _mode == audio::orchestra::mode_input
	     && m_mode == audio::orchestra::mode_output
	     && m_device[0] == _device) {
		// Only one callback procedure per device.
		m_mode = audio::orchestra::mode_duplex;
	} else {
#if defined(MAC_OS_X_VERSION_10_5) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
		result = AudioDeviceCreateIOProcID(id, &audio::orchestra::api::Core::callbackEvent, this, &m_private->procId[modeToIdTable(_mode)]);
#else
		// deprecated in favor of AudioDeviceCreateIOProcID()
		result = AudioDeviceAddIOProc(id, &audio::orchestra::api::Core::callbackEvent, this);
#endif
		if (result != noErr) {
			ATA_ERROR("system error setting callback for device (" << _device << ").");
			goto error;
		}
		if (    m_mode == audio::orchestra::mode_output
		     && _mode == audio::orchestra::mode_input) {
			m_mode = audio::orchestra::mode_duplex;
		} else {
			m_mode = _mode;
		}
	}
	// Setup the device property listener for over/underload.
	property.mSelector = kAudioDeviceProcessorOverload;
	result = AudioObjectAddPropertyListener(id, &property, &audio::orchestra::api::Core::xrunListener, this);
	return true;
error:
	m_userBuffer[0].clear();
	m_userBuffer[1].clear();
	if (m_deviceBuffer) {
		free(m_deviceBuffer);
		m_deviceBuffer = 0;
	}
	m_state = audio::orchestra::state::closed;
	ATA_VERBOSE("Set state as closed");
	return false;
}
Ejemplo n.º 2
0
tbool CDeviceCoreAudio::Start()
{
	OSErr err1 = AudioDeviceAddIOProc(mAudioDeviceID, HALIOProc, (void*)this);
	OSErr err2 = AudioDeviceStart(mAudioDeviceID, HALIOProc);

	return ((err1 == 0) && (err2 == 0));
} // Start
Ejemplo n.º 3
0
static GVBool gviHardwareStartCapture(GVDevice device)
{
	GVIHardwareData * data = (GVIHardwareData *)device->m_data;
	OSStatus result;

	// now capturing
	data->m_capturing = GVTrue;

	// add the IO proc
	result = AudioDeviceAddIOProc((AudioDeviceID)device->m_deviceID, gviHardwareCaptureIOProc, device);
	if(result != noErr)
	{
		data->m_capturing = GVFalse;
		return GVFalse;
	}

	// start it
	result = AudioDeviceStart((AudioDeviceID)device->m_deviceID, gviHardwareCaptureIOProc);
	if(result != noErr)
	{
		data->m_capturing = GVFalse;
		return GVFalse;
	}

	return GVTrue;
}
Ejemplo n.º 4
0
static GVBool gviHardwareStartPlayback(GVDevice device)
{
	GVIHardwareData * data = (GVIHardwareData *)device->m_data;
	OSStatus result;

	// now playing
	data->m_playing = GVTrue;

	// reset the playback clock
	data->m_playbackClock = 0;

	// add the IO proc
	result = AudioDeviceAddIOProc((AudioDeviceID)device->m_deviceID, gviHardwarePlaybackIOProc, device);
	if(result != noErr)
	{
		data->m_playing = GVFalse;
		return GVFalse;
	}

	// start it
	result = AudioDeviceStart((AudioDeviceID)device->m_deviceID, gviHardwarePlaybackIOProc);
	if(result != noErr)
	{
		data->m_playing = GVFalse;
		return GVFalse;
	}

	return GVTrue;
}
Ejemplo n.º 5
0
// ------------------------------------------------------
// Name: AUDIO_Init_Driver()
// Desc: Init the audio driver
int AUDIO_Init_Driver(void (*Mixer)(Uint8 *, Uint32))
{
    AUDIO_Mixer = Mixer;

    AUDIO_Device = kAudioDeviceUnknown;
    Amount = sizeof(AudioDeviceID);
    if(AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice,
                                &Amount,
                                (void *) &AUDIO_Device) == noErr)
    {
        if(AudioDeviceAddIOProc(AUDIO_Device,
                                AUDIO_Callback,
                                NULL) == noErr)
        {
            return(AUDIO_Create_Sound_Buffer(AUDIO_Milliseconds));
        }

#if !defined(__STAND_ALONE__) && !defined(__WINAMP__)
        else
        {
            Message_Error("Error while calling AudioDeviceAddIOProc()");
        }
#endif

    }

#if !defined(__STAND_ALONE__) && !defined(__WINAMP__)
    else
    {
        Message_Error("Error while calling AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice)");
    }
#endif

    return(FALSE);
}
Ejemplo n.º 6
0
static OSStatus AudioDeviceCreateIOProcID(AudioDeviceID dev,
                                          AudioDeviceIOProc proc,
                                          void *data,
                                          AudioDeviceIOProcID *procid)
{
  *procid = proc;
  return AudioDeviceAddIOProc(dev, proc, data);
}
Ejemplo n.º 7
0
static void set_input_callback(AudioDeviceID id, AudioDeviceIOProc cbk, void *data) {
	OSStatus err = noErr;

	err = AudioDeviceAddIOProc(id, cbk, data);
	if (err != noErr) {
		DBG_DYNA_AUDIO_DRV("!!CoreAudio: can't set input callback\n");
	}	
}
Ejemplo n.º 8
0
static au_instance_t *audiounits_create_recorder(SEXP source, float rate, int chs, int flags) {
	UInt32 propsize=0;
	OSStatus err;
	
	au_instance_t *ap = (au_instance_t*) calloc(sizeof(au_instance_t), 1);
	ap->source = source;
	ap->sample_rate = rate;
	ap->done = NO;
	ap->position = 0;
	ap->length = LENGTH(source);
	ap->stereo = (chs == 2) ? YES : NO;
	
	propsize = sizeof(ap->inDev);
	err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &propsize, &ap->inDev);
	if (err) {
		free(ap);
		Rf_error("unable to find default audio input (%08x)", err);
	}
	
	propsize = sizeof(ap->fmtIn);
	err = AudioDeviceGetProperty(ap->inDev, 0, YES, kAudioDevicePropertyStreamFormat, &propsize, &ap->fmtIn);
	if (err) {
		free(ap);
		Rf_error("unable to retrieve audio input format (%08x)", err);
	}
	
	/* Rprintf(" recording format: %f, chs: %d, fpp: %d, bpp: %d, bpf: %d, flags: %x\n", ap->fmtIn.mSampleRate, ap->fmtIn.mChannelsPerFrame, ap->fmtIn.mFramesPerPacket, ap->fmtIn.mBytesPerPacket, ap->fmtIn.mBytesPerFrame, ap->fmtIn.mFormatFlags); */
	
	ap->srFrac = 1.0;
	if (ap->fmtIn.mSampleRate != ap->sample_rate) ap->srFrac = ap->sample_rate / ap->fmtIn.mSampleRate;
	ap->srRun = 0.0;
	
#if defined(MAC_OS_X_VERSION_10_5) && (MAC_OS_X_VERSION_MIN_REQUIRED>=MAC_OS_X_VERSION_10_5)
	err = AudioDeviceCreateIOProcID(ap->inDev, inputRenderProc, ap, &ap->inIOProcID );
#else
	err = AudioDeviceAddIOProc(ap->inDev, inputRenderProc, ap);
#endif
	if (err) {
		free(ap);
		Rf_error("unable to register recording callback (%08x)", err);
	}
	R_PreserveObject(ap->source);
	Rf_setAttrib(ap->source, Rf_install("rate"), Rf_ScalarInteger(rate)); /* we adjust the rate */
	Rf_setAttrib(ap->source, Rf_install("bits"), Rf_ScalarInteger(16)); /* we say it's 16 because we don't know - float is always 32-bit */
	Rf_setAttrib(ap->source, Rf_install("class"), Rf_mkString("audioSample"));
	if (ap->stereo) {
		SEXP dim = Rf_allocVector(INTSXP, 2);
		INTEGER(dim)[0] = 2;
		INTEGER(dim)[1] = LENGTH(ap->source) / 2;
		Rf_setAttrib(ap->source, R_DimSymbol, dim);
	}
	return ap;
}
Ejemplo n.º 9
0
bool CCoreAudioDevice::AddIOProc(AudioDeviceIOProc ioProc, void* pCallbackData)
{
  if (!m_DeviceId || m_IoProc) // Only one IOProc at a time
    return false;
  
  OSStatus ret = AudioDeviceAddIOProc(m_DeviceId, ioProc, pCallbackData);  
  if (ret)
  {
    CLog::Log(LOGERROR, "CCoreAudioDevice::Stop: Unable to add IOProc. Error = 0x%08x (%4.4s).", ret, CONVERT_OSSTATUS(ret));
    return false;
  }
  m_IoProc = ioProc;
  CLog::Log(LOGDEBUG, "CCoreAudioDevice::AddIOProc: IOProc set for device 0x%04x", m_DeviceId);
  return true;
}
Ejemplo n.º 10
0
static int
ca_init (void) {
    UInt32 sz;
    char device_name[128];

    sz = sizeof(device_id);
    if (AudioHardwareGetProperty (kAudioHardwarePropertyDefaultOutputDevice, &sz, &device_id)) {
        return -1;
    }

    sz = sizeof (device_name);
    if (AudioDeviceGetProperty (device_id, 1, 0, kAudioDevicePropertyDeviceName, &sz, device_name)) {
           return -1;
    }
    
    sz = sizeof (default_format);
    if (AudioDeviceGetProperty (device_id, 0, 0, kAudioDevicePropertyStreamFormat, &sz, &default_format)) {
        return -1;
    }

    UInt32 bufsize = 4096;
    sz = sizeof (bufsize);
    if (AudioDeviceSetProperty(device_id, NULL, 0, 0, kAudioDevicePropertyBufferFrameSize, sz, &bufsize)) {
        fprintf (stderr, "Failed to set buffer size\n");
    }

    if (ca_apply_format ()) {
        return -1;
    }

    if (AudioDeviceAddIOProc (device_id, ca_buffer_callback, NULL)) {
        return -1;
    }
    
    if (AudioDeviceAddPropertyListener (device_id, 0, 0, kAudioDevicePropertyStreamFormat, ca_fmtchanged, NULL)) {
        return -1;
    }
    
    ca_fmtchanged(0, 0, 0, kAudioDevicePropertyStreamFormat, NULL);

    state = OUTPUT_STATE_STOPPED;

    return 0;
}
Ejemplo n.º 11
0
// start the device attached to the stream.
// 
static int Stream_startSema(Stream *s, int semaIndex)
{
  AudioDeviceIOProc ioProc= s->direction ? ioProcInput : ioProcOutput;

  debugf("stream %p[%d] startSema: %d\n", s, s->direction, semaIndex);
  
  s->semaphore= semaIndex;	// can be zero
  if (checkError(AudioDeviceAddIOProc(s->id, ioProc, (void *)s),
		 "Add", "ioProcOut"))
    return 0;
  if (checkError(AudioDeviceStart(s->id, ioProc),
		 "DeviceStart", "ioProcOut"))
    {
      AudioDeviceRemoveIOProc(s->id, ioProc);
      return 0;
    }
  debugf("stream %p[%d] running\n", s, s->direction);
  return 1;
}
    bool start (AudioIODeviceCallback* cb)
    {
        if (! started)
        {
            callback = nullptr;

            if (deviceID != 0)
            {
               #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
                if (OK (AudioDeviceAddIOProc (deviceID, audioIOProc, this)))
               #else
                if (OK (AudioDeviceCreateIOProcID (deviceID, audioIOProc, this, &audioProcID)))
               #endif
                {
                    if (OK (AudioDeviceStart (deviceID, audioIOProc)))
                    {
                        started = true;
                    }
                    else
                    {
                       #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
                        OK (AudioDeviceRemoveIOProc (deviceID, audioIOProc));
                       #else
                        OK (AudioDeviceDestroyIOProcID (deviceID, audioProcID));
                        audioProcID = 0;
                       #endif
                    }
                }
            }
        }

        if (started)
        {
            const ScopedLock sl (callbackLock);
            callback = cb;
        }

        return started && (inputDevice == nullptr || inputDevice->start (cb));
    }
Ejemplo n.º 13
0
int audev_init_device(char *wantdevname, long ratewanted, int verbose, extraopt_t *extra)
{
  int bx, res;
  OSStatus status;
  int channels;
  long rate;
  long fragsize;
  int listdevices = FALSE;
  AudioDeviceID wantdevid;
  AudioDeviceID wantedaudev;
  extraopt_t *opt;
  UInt32 propsize;
  UInt32 bytecount;
  struct AudioStreamBasicDescription streamdesc;
#define LEN_DEVICE_NAME 128
  char devicename[LEN_DEVICE_NAME];

  if (verbose) {
    printf("Boodler: OSX CoreAudio sound driver.\n");
  }

  fragsize = 32768;
  bufcount = 6;

  for (opt=extra; opt->key; opt++) {
    if (!strcmp(opt->key, "buffersize") && opt->val) {
      fragsize = atol(opt->val);
    }
    else if (!strcmp(opt->key, "buffercount") && opt->val) {
      bufcount = atoi(opt->val);
    }
    else if (!strcmp(opt->key, "listdevices")) {
      listdevices = TRUE;
    }
  }

  if (bufcount < 2)
    bufcount = 2;

  if (audevice != kAudioDeviceUnknown) {
    fprintf(stderr, "Sound device is already open.\n");
    return FALSE;
  }

  wantedaudev = kAudioDeviceUnknown;

  /* If the given device name is a string representation of an
     integer, work out the integer. */
  wantdevid = kAudioDeviceUnknown;
  if (wantdevname) {
    char *endptr = NULL;
    wantdevid = strtol(wantdevname, &endptr, 10);
    if (!endptr || endptr == wantdevname || (*endptr != '\0'))
      wantdevid = kAudioDeviceUnknown;
  }

  if (listdevices || wantdevname) {
    int ix, jx;
    int device_count;
#define LEN_DEVICE_LIST 16
    AudioDeviceID devicelist[LEN_DEVICE_LIST];  

    propsize = LEN_DEVICE_LIST * sizeof(AudioDeviceID);
    status = AudioHardwareGetProperty(kAudioHardwarePropertyDevices,
      &propsize, devicelist);
    if (status) {
      fprintf(stderr, "Could not get list of audio devices.\n");
      return FALSE;
    }
    device_count = propsize / sizeof(AudioDeviceID);

    for (ix=0; ix<device_count; ix++) {
      AudioDeviceID tmpaudev = devicelist[ix];

      /* Determine if this is an output device. */
      status = AudioDeviceGetPropertyInfo(tmpaudev, 0, 0, 
	kAudioDevicePropertyStreamConfiguration, &propsize, NULL);
      if (status) {
	fprintf(stderr, "Could not get audio property info.\n");
	return FALSE;
      }

      AudioBufferList *buflist = (AudioBufferList *)malloc(propsize);
      status = AudioDeviceGetProperty(tmpaudev, 0, 0, 
	kAudioDevicePropertyStreamConfiguration, &propsize, buflist);
      if (status) {
	fprintf(stderr, "Could not get audio property info.\n");
	return FALSE;
      }

      int hasoutput = FALSE;

      for (jx=0; jx<buflist->mNumberBuffers; jx++) {
	if (buflist->mBuffers[jx].mNumberChannels > 0) {
	  hasoutput = TRUE;
	}
      }

      free(buflist);
      buflist = NULL;

      if (!hasoutput) {
	/* skip this device. */
	continue;
      }

      /* Determine the device name. */

      propsize = LEN_DEVICE_NAME * sizeof(char);
      status = AudioDeviceGetProperty(tmpaudev, 1, 0,
	kAudioDevicePropertyDeviceName, &propsize, devicename);
      if (status) {
	fprintf(stderr, "Could not get audio device name.\n");
	return FALSE;
      }

      if (listdevices)
	printf("Found device ID %d: \"%s\".\n", (int)tmpaudev, devicename);

      /* Check if the desired name matches (a prefix of) the device name. */
      if (wantdevname && !strncmp(wantdevname, devicename, 
	    strlen(wantdevname))) {
	wantedaudev = tmpaudev;
      }

      /* Check if the int version of the desired name matches the device ID. */
      if (wantdevid != kAudioDeviceUnknown && wantdevid == tmpaudev) {
	wantedaudev = tmpaudev;
      }
    }
  }

  if (wantdevname) {
    audevice = wantedaudev;
  }
  else {
    propsize = sizeof(audevice);
    status = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice,
      &propsize, &audevice);
    if (status) {
      fprintf(stderr, "Could not get audio default device.\n");
      return FALSE;
    }
  }

  if (audevice == kAudioDeviceUnknown) {
    fprintf(stderr, "Audio default device is unknown.\n");
    return FALSE;
  }

  propsize = LEN_DEVICE_NAME * sizeof(char);
  status = AudioDeviceGetProperty(audevice, 1, 0,
    kAudioDevicePropertyDeviceName, &propsize, devicename);
  if (status) {
    fprintf(stderr, "Could not get audio device name.\n");
    return FALSE;
  }

  if (verbose) {
    printf("Got device ID %d: \"%s\".\n", (int)audevice, devicename);
  }

  if (ratewanted) {
    memset(&streamdesc, 0, sizeof(streamdesc));
    streamdesc.mSampleRate = ratewanted;

    propsize = sizeof(streamdesc);

    status = AudioDeviceSetProperty(audevice, NULL, 0, 0,
      kAudioDevicePropertyStreamFormatMatch, propsize, &streamdesc);
    if (status) {
      fprintf(stderr, "Could not set sample rate; continuing.\n");
    }
  }

  {
    bytecount = fragsize;

    propsize = sizeof(bytecount);

    status = AudioDeviceSetProperty(audevice, NULL, 0, 0,
      kAudioDevicePropertyBufferSize, propsize, &bytecount);
    if (status) {
      fprintf(stderr, "Could not set buffer size; continuing.\n");
    }
  }

  propsize = sizeof(struct AudioStreamBasicDescription);
  status = AudioDeviceGetProperty(audevice, 1, 0,
    kAudioDevicePropertyStreamFormat, &propsize, &streamdesc);
  if (status) {
    fprintf(stderr, "Could not get audio device description.\n");
    return FALSE;
  }

  rate = streamdesc.mSampleRate;

  if (streamdesc.mFormatID != kAudioFormatLinearPCM) {
    fprintf(stderr, "Audio device format is not LinearPCM; exiting.\n");
    return FALSE;    
  }

  if (streamdesc.mChannelsPerFrame != 2) {
    fprintf(stderr, "Audio device is not stereo; exiting.\n");
    return FALSE;
  }
  channels = 2;

  if (!(streamdesc.mFormatFlags & kLinearPCMFormatFlagIsFloat)) {
    fprintf(stderr, "Audio device is not floating-point; exiting.\n");
    return FALSE;
  }

  propsize = sizeof(bytecount);
  status = AudioDeviceGetProperty(audevice, 1, 0,
    kAudioDevicePropertyBufferSize, &propsize, &bytecount);
  if (status) {
    fprintf(stderr, "Could not get audio device buffer size.\n");
    return FALSE;
  }

  fragsize = bytecount;
  if (verbose) {
    printf("%ld bytes per buffer.\n", fragsize);
  }

  if (verbose) {
    printf("%d buffers in queue.\n", bufcount);
  }

  /* Everything's figured out. */

  sound_rate = rate;
  sound_channels = channels;
  sound_buffersize = fragsize;

  framesperbuf = sound_buffersize / (sizeof(float) * sound_channels);
  samplesperbuf = framesperbuf * sound_channels;
  if (verbose) {
    printf("%ld frames (%ld samples) per buffer.\n",
	   framesperbuf, samplesperbuf);
    printf("%ld frames per second.\n",
	   rate);
  }

  emptying = 0;
  filling = 0;

  bailing = FALSE;

  valbuffer = (long *)malloc(sizeof(long) * samplesperbuf);
  if (!valbuffer) {
    fprintf(stderr, "Unable to allocate sound buffer.\n");
    return FALSE;     
  }
  memset(valbuffer, 0, sizeof(long) * samplesperbuf);

  rawbuffer = (buffer_t *)malloc(sizeof(buffer_t) * bufcount);
  memset(rawbuffer, 0, sizeof(buffer_t) * bufcount);

  for (bx=0; bx<bufcount; bx++) {
    buffer_t *buffer = &rawbuffer[bx];

    buffer->full = FALSE;

    buffer->buf = (float *)malloc(sound_buffersize);
    if (!buffer->buf) {
      fprintf(stderr, "Unable to allocate sound buffer.\n");
      /* free stuff */
      return FALSE;    
    }
    memset(buffer->buf, 0, sound_buffersize);

    res = pthread_mutex_init(&buffer->mutex, NULL);
    if (res) {
      fprintf(stderr, "Unable to init mutex.\n");
      /* free stuff */
      return FALSE;
    }

    res = pthread_cond_init(&buffer->cond, NULL);
    if (res) {
      fprintf(stderr, "Unable to init cond.\n");
      /* free stuff */
      return FALSE;
    }

  }

  /* AudioDeviceAddIOProc is deprecated as of OSX 10.5. Use the
     osxaq driver instead. */
  status = AudioDeviceAddIOProc(audevice, PlaybackIOProc, (void *)1);
  if (status) {
    fprintf(stderr, "Could not add IOProc to device.\n");
    return FALSE;
  }

  started = FALSE;

  return TRUE;
}
Ejemplo n.º 14
0
/*return value == 0 sucess
               == -1 fails
 */
static int open_output(void)
{
    OSStatus				err = 0; //no err
    UInt32				count,
                                        bufferSize;
    AudioDeviceID			device = kAudioDeviceUnknown;
    AudioStreamBasicDescription		format;

    // get the default output device for the HAL
    count = sizeof(globals.device);
    // it is required to pass the size of the data to be returned
    err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice,
                                   &count, (void *) &device);
    if (err != 0) goto Bail;
    
    // get the buffersize that the default device uses for IO
    count = sizeof(globals.deviceBufferSize);
              // it is required to pass the size of the data to be returned
    err = AudioDeviceGetProperty(device, 0, 0, kAudioDevicePropertyBufferSize,
                                 &count, &bufferSize);
    if (err != 0) goto Bail;
   
    if( globals.deviceBufferSize>BUFLEN ){
        fprintf(stderr, "globals.deviceBufferSize NG: %ld\n",
                globals.deviceBufferSize);
        exit(1);
    }
   
         // get a description of the data format used by the default device
    count = sizeof(globals.deviceFormat);
         // it is required to pass the size of the data to be returned
    err = AudioDeviceGetProperty(device, 0, 0,
                                 kAudioDevicePropertyStreamFormat,
                                 &count, &format);
    if (err != 0) goto Bail;
    FailWithAction(format.mFormatID != kAudioFormatLinearPCM, err = -1, Bail);
                    // bail if the format is not linear pcm
    
    // everything is ok so fill in these globals
    globals.device = device;
    globals.deviceBufferSize = bufferSize;
    globals.deviceFormat = format;
    init_variable();
    
    err = AudioDeviceAddIOProc(globals.device, appIOProc, 0 );
                    // setup our device with an IO proc
    if (err != 0) goto Bail;

    globals.deviceFormat.mSampleRate = dpm.rate;

#if 0
    globals.deviceFormat.mFormatFlags =  kLinearPCMFormatFlagIsBigEndian
                                       | kLinearPCMFormatFlagIsPacked
                                       | kLinearPCMFormatFlagIsSignedInteger;
    globals.deviceFormat.mBytesPerPacket = 4;
    globals.deviceFormat.mBytesPerFrame = 4;
    globals.deviceFormat.mBitsPerChannel = 0x10;
    
    err = AudioDeviceSetProperty(device, &inWhen, 0, 0,
                                 kAudioDevicePropertyStreamFormat,
                                 count, &globals.deviceFormat);
    if (err != 0) goto Bail;
#endif

#if 0
    fprintf(stderr, "deviceBufferSize = %d\n", globals.deviceBufferSize);
    fprintf(stderr, "mSampleRate = %g\n", globals.deviceFormat.mSampleRate);
    fprintf(stderr, "mFormatID = 0x%08x\n", globals.deviceFormat.mFormatID);
    fprintf(stderr, "mFormatFlags = 0x%08x\n",
            globals.deviceFormat.mFormatFlags);
    fprintf(stderr, "mBytesPerPacket = 0x%08x\n",
            globals.deviceFormat.mBytesPerPacket);
    fprintf(stderr, "mBytesPerFrame = 0x%08x\n",
            globals.deviceFormat.mBytesPerFrame);
    fprintf(stderr, "mBitsPerChannel = 0x%08x\n",
            globals.deviceFormat.mBitsPerChannel);
#endif

Bail:
    return (err);
}
Ejemplo n.º 15
0
void	AudioThruEngine::Start()
{
	if (mRunning) return;
	if (!mInputDevice.Valid() || !mOutputDevice.Valid()) {
		//printf("invalid device\n");
		return;
	}

	// $$$ should do some checks on the format/sample rate matching
	if (mInputDevice.mFormat.mSampleRate != mOutputDevice.mFormat.mSampleRate) {
		if (MatchSampleRate(false)) {
			printf("Error - sample rate mismatch: %f / %f\n", mInputDevice.mFormat.mSampleRate, mOutputDevice.mFormat.mSampleRate);
			return;
		}
	}


	/*if (mInputDevice.mFormat.mChannelsPerFrame != mOutputDevice.mFormat.mChannelsPerFrame
	|| mInputDevice.mFormat.mBytesPerFrame != mOutputDevice.mFormat.mBytesPerFrame) {
		printf("Error - format mismatch: %ld / %ld channels, %ld / %ld bytes per frame\n",
			mInputDevice.mFormat.mChannelsPerFrame, mOutputDevice.mFormat.mChannelsPerFrame,
			mInputDevice.mFormat.mBytesPerFrame, mOutputDevice.mFormat.mBytesPerFrame);
		return;
	}*/
	//mErrorMessage[0] = '\0';
	mInputBuffer->Allocate(mInputDevice.mFormat.mBytesPerFrame, UInt32(kSecondsInRingBuffer * mInputDevice.mFormat.mSampleRate));
	mSampleRate = mInputDevice.mFormat.mSampleRate;
	
	mWorkBuf = new Byte[mInputDevice.mBufferSizeFrames * mInputDevice.mFormat.mBytesPerFrame];
	memset(mWorkBuf, 0, mInputDevice.mBufferSizeFrames * mInputDevice.mFormat.mBytesPerFrame);
		
	mRunning = true;
	
#if USE_AUDIODEVICEREAD
	UInt32 streamListSize;
	verify_noerr (AudioDeviceGetPropertyInfo(gInputDevice, 0, true, kAudioDevicePropertyStreams, &streamListSize, NULL));
	UInt32 nInputStreams = streamListSize / sizeof(AudioStreamID);
	
	propsize = offsetof(AudioBufferList, mBuffers[nInputStreams]);
	gInputIOBuffer = (AudioBufferList *)malloc(propsize);
	verify_noerr (AudioDeviceGetProperty(gInputDevice, 0, true, kAudioDevicePropertyStreamConfiguration, &propsize, gInputIOBuffer));
	gInputIOBuffer->mBuffers[0].mData = malloc(gInputIOBuffer->mBuffers[0].mDataByteSize);
	
	verify_noerr (AudioDeviceSetProperty(gInputDevice, NULL, 0, true, kAudioDevicePropertyRegisterBufferList, propsize, gInputIOBuffer));
#endif
	
	mInputProcState = kStarting;
	mOutputProcState = kStarting;
	
	verify_noerr (AudioDeviceAddIOProc(mInputDevice.mID, InputIOProc, this));
	verify_noerr (AudioDeviceStart(mInputDevice.mID, InputIOProc));
	
	if (mInputDevice.CountChannels() == 2)
		mOutputIOProc = OutputIOProc;
	else
		mOutputIOProc = OutputIOProc16;
		

	verify_noerr (AudioDeviceAddIOProc(mOutputDevice.mID, mOutputIOProc, this));
	verify_noerr (AudioDeviceStart(mOutputDevice.mID, mOutputIOProc));

//	UInt32 propsize = sizeof(UInt32);
//	UInt32 isAlreadyRunning;
//	err =  (AudioDeviceGetProperty(mOutputDevice.mID, 0, false, kAudioDevicePropertyDeviceIsRunning, &propsize, &isAlreadyRunning));
//	if (isAlreadyRunning)
//		mOutputProcState = kRunning;
//	else
		
	
	while (mInputProcState != kRunning || mOutputProcState != kRunning)
		usleep(1000);
	
//	usleep(12000);
	ComputeThruOffset();
}
Ejemplo n.º 16
0
int
audio_output_open(void)
{
	UInt32 size;

	/* Obtain the audio device ID */
	size = sizeof adid;
	if (AudioHardwareGetProperty(
	    kAudioHardwarePropertyDefaultOutputDevice,
	    &size, &adid) != 0 || adid == kAudioDeviceUnknown)
		goto error;

	/* Adjust the stream format */
	size = sizeof afmt;
	if (AudioDeviceGetProperty(adid, 0, false,
	    kAudioDevicePropertyStreamFormat, &size, &afmt) != 0 ||
	    afmt.mFormatID != kAudioFormatLinearPCM)
		goto error;

	/* To be set on the first run */
	afmt.mSampleRate = 0;
	afmt.mChannelsPerFrame = 0;
	afmt.mBytesPerFrame = afmt.mChannelsPerFrame * sizeof (float);
	afmt.mBytesPerPacket = afmt.mBytesPerFrame * afmt.mFramesPerPacket;

	/* Decide what buffer size to use */
	size = sizeof abuflen;
	abuflen = 32768;
	AudioDeviceSetProperty(adid, 0, 0, false,
	    kAudioDevicePropertyBufferSize, size, &abuflen);
	if (AudioDeviceGetProperty(adid, 0, false,
	    kAudioDevicePropertyBufferSize, &size, &abuflen) != 0)
		goto error;

#ifdef BUILD_VOLUME
	/* Store the audio channels */
	size = sizeof achans;
	AudioDeviceGetProperty(adid, 0, false,
	    kAudioDevicePropertyPreferredChannelsForStereo, &size, &achans);
#endif /* BUILD_VOLUME */

	/* The buffer size reported is in floats */
	abuflen /= sizeof(float);
	abufnew = g_malloc(abuflen * sizeof(int16_t));
	abufcur = g_malloc(abuflen * sizeof(int16_t));

	/* Locking down the buffer length */
	abuflock = g_mutex_new();
	abufdrained = g_cond_new();

	/* Add our own I/O handling routine */
#ifdef MAC_OS_X_VERSION_10_5
	if (AudioDeviceCreateIOProcID(adid, audio_output_ioproc, NULL,
	    &aprocid) != 0)
#else /* !MAC_OS_X_VERSION_10_5 */
	if (AudioDeviceAddIOProc(adid, audio_output_ioproc, NULL) != 0)
#endif /* MAC_OS_X_VERSION_10_5 */
		goto error;

	return (0);
error:
	g_printerr("%s\n", _("Cannot open the audio device."));
	return (-1);
}
Ejemplo n.º 17
0
void audio_init_input ()
{
	unsigned long size, indev, buflen;
	AudioStreamBasicDescription info;

	/* Get default input device id. */
	size = sizeof (indev);
	if (AudioHardwareGetProperty (kAudioHardwarePropertyDefaultInputDevice,
	    &size, &indev) != 0 || indev == kAudioDeviceUnknown) {
		fprintf (stderr, "audio: cannot get input device\n");
		exit (-1);
	}
#if 0
	/* Get input format. */
	size = sizeof (info);
	if (AudioDeviceGetProperty (indev, 0, true,
	    kAudioDevicePropertyStreamFormat, &size, &info) != 0) {
		fprintf (stderr, "audio: cannot get input stream format\n");
		exit (-1);
	}
        printf ("Format: id %08lx, flags %lx\n", info.mFormatID, info.mFormatFlags);
        printf ("Frames per packet: %ld\n", info.mFramesPerPacket);
        printf ("Channels per frame: %ld\n", info.mChannelsPerFrame);
        printf ("Bytes per packet: %ld\n", info.mBytesPerPacket);
        printf ("Bytes per frame: %ld\n", info.mBytesPerFrame);
        printf ("Bits per channel: %ld\n", info.mBitsPerChannel);
	printf ("Sample rate: %g\n", info.mSampleRate);
#endif
	/* Set required input format. */
        info.mFormatID = kAudioFormatLinearPCM;
        info.mFormatFlags = kLinearPCMFormatFlagIsBigEndian |
		kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsFloat;
	info.mSampleRate = 44100;
        info.mChannelsPerFrame = 2; /* stereo */
        info.mFramesPerPacket = 1;
	info.mBitsPerChannel = 8 * sizeof (float);
	info.mBytesPerPacket = info.mBitsPerChannel / 8 * info.mChannelsPerFrame;
	info.mBytesPerFrame = info.mBytesPerPacket / info.mFramesPerPacket;
	size = sizeof (info);
	if (AudioDeviceSetProperty (indev, 0, 0, true,
	    kAudioDevicePropertyStreamFormat, size, &info) != 0) {
		fprintf (stderr, "audio: cannot setup input stream format\n");
		exit (-1);
	}

	/* Set buffer length. */
	size = sizeof (buflen);
	buflen = info.mBytesPerPacket * 2048;
	if (AudioDeviceSetProperty (indev, 0, 0, true,
	    kAudioDevicePropertyBufferSize, size, &buflen) != 0) {
		fprintf (stderr, "audio: cannot set buffer length\n");
		exit (-1);
	}

	/* Get buffer length. */
	size = sizeof (buflen);
	if (AudioDeviceGetProperty (indev, 0, true,
	    kAudioDevicePropertyBufferSize, &size, &buflen) != 0) {
		fprintf (stderr, "audio: cannot get buffer length\n");
		exit (-1);
	}
	printf ("Buffer length: %ld bytes\n", buflen);

	/* Set the IO proc that CoreAudio will call when it needs data */
	if (AudioDeviceAddIOProc (indev, audio_callback, 0) != 0) {
		fprintf (stderr, "audio: cannot add i/o procedure\n");
		exit (-1);
	}

	/* Start callback */
	if (AudioDeviceStart (indev, audio_callback) != 0) {
		fprintf (stderr, "audio: cannot start device\n");
		exit (-1);
	}
}
Ejemplo n.º 18
0
int macosx_audio_open(audio_desc_t ad, audio_format* ifmt, audio_format *ofmt)
{
	OSStatus err = noErr;
	UInt32   propertySize;
	Boolean  writable;
	obtained_ = false;
	add = ad;
	//dev[0] = devices[ad];
	UNUSED(ofmt);

	// Get the default input device ID. 
	err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDefaultInputDevice, &propertySize, &writable);              
	if (err != noErr) {
		return 0;
	}
	err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &propertySize, &(devices[ad].inputDeviceID_));
	if (err != noErr) {
		debug_msg("error kAudioHardwarePropertyDefaultInputDevice");
		return 0;
	}
	if (devices[ad].inputDeviceID_ == kAudioDeviceUnknown) {
		debug_msg("error kAudioDeviceUnknown");
		return 0;
	}
	// Get the input stream description.
	err = AudioDeviceGetPropertyInfo(devices[ad].inputDeviceID_, 0, true, kAudioDevicePropertyStreamFormat, &propertySize, &writable);
	if (err != noErr) {
		debug_msg("error AudioDeviceGetPropertyInfo");
		return 0;
	}
	err = AudioDeviceGetProperty(devices[ad].inputDeviceID_, 0, true, kAudioDevicePropertyStreamFormat, &propertySize, &(devices[ad].inputStreamBasicDescription_));
	//printf("inputStreamBasicDescription_.mBytesPerFrame %d\n", devices[add].inputStreamBasicDescription_);
	if (err != noErr) {
		debug_msg("error AudioDeviceGetProperty");
		return 0;
	}

	// nastavime maly endian
	devices[ad].inputStreamBasicDescription_.mFormatFlags &= (kAudioFormatFlagIsBigEndian & 0);

	if (writable) {
	        err = AudioDeviceSetProperty(devices[ad].inputDeviceID_, NULL, 0, true, kAudioDevicePropertyStreamFormat, sizeof(AudioStreamBasicDescription), &(devices[ad].inputStreamBasicDescription_));
	        if (err != noErr) printf("err: AudioDeviceSetProperty: kAudioDevicePropertyStreamFormat\n");
	}
	
	/* set the buffer size of the device */
	
	/*
	int bufferByteSize = 8192;
	propertySize = sizeof(bufferByteSize);
	err = AudioDeviceSetProperty(devices[ad].inputDeviceID_, NULL, 0, true, kAudioDevicePropertyBufferSize, propertySize, &bufferByteSize);
	if (err != noErr) debug_msg("err: Set kAudioDevicePropertyBufferSize to %d\n", bufferByteSize);
	else debug_msg("sucessfully set kAudioDevicePropertyBufferSize to %d\n", bufferByteSize);
	*/

        // Set the device sample rate -- a temporary fix for the G5's
        //   built-in audio and possibly other audio devices.
	Boolean IsInput = 0;
	int inChannel = 0;
         
	Float64 theAnswer = 44100;
	UInt32 theSize = sizeof(theAnswer);
	err = AudioDeviceSetProperty(devices[ad].inputDeviceID_, NULL, inChannel, IsInput,
                                kAudioDevicePropertyNominalSampleRate, theSize, &theAnswer);

	if (err != noErr) {
		debug_msg("error AudioDeviceSetProperty\n");
		return 0;
	}
	debug_msg("Sample rate, %f\n", theAnswer);
#if defined(MAC_OS_X_VERSION_10_5) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
	err = AudioDeviceCreateIOProcID(devices[ad].inputDeviceID_, audioIOProc, (void*)NULL, &devices[ad].inputDeviceProcID_);
	if (err != noErr) {
		debug_msg("error AudioDeviceCreateIOProcID, %s\n", GetMacOSStatusCommentString(err));
		return 0;
	}
	err = OpenADefaultComponent(kAudioUnitType_Output, kAudioUnitSubType_DefaultOutput, &(devices[ad].outputUnit_));
	// The HAL AU maybe a better way to in the future...
	//err = OpenADefaultComponent(kAudioUnitType_Output, kAudioUnitSubType_HALOutput, &(devices[ad].outputUnit_));
	if (err != noErr) {
		debug_msg("error OpenADefaultComponent\n");
		return 0;
	}
#else
	// Register the AudioDeviceIOProc.
	err = AudioDeviceAddIOProc(devices[ad].inputDeviceID_, audioIOProc, NULL);
	if (err != noErr) {
		debug_msg("error AudioDeviceAddIOProc\n");
		return 0;
	}
	err = OpenDefaultAudioOutput(&(devices[ad].outputUnit_));
	if (err != noErr) {
		debug_msg("error OpenDefaultAudioOutput\n");
		return 0;
	}
#endif
	// Register a callback function to provide output data to the unit.
	devices[ad].input.inputProc = outputRenderer;
	devices[ad].input.inputProcRefCon = 0;
	/* These would be needed if HAL used
	 * UInt32 enableIO =1; 
	err = AudioUnitSetProperty(devices[ad].outputUnit_, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, (const void*)&enableIO, sizeof(UInt32));
	enableIO=0;
	err = AudioUnitSetProperty(devices[ad].outputUnit_, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, (const void*)&enableIO, sizeof(UInt32));
	if (err != noErr) {
		debug_msg("error AudioUnitSetProperty EnableIO with error %ld: %s\n", err, GetMacOSStatusErrorString(err));
		return 0;
	}*/
#if defined(MAC_OS_X_VERSION_10_5) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
	err = AudioUnitSetProperty(devices[ad].outputUnit_, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, 0, &(devices[ad].input), sizeof(AURenderCallbackStruct));
#else
	err = AudioUnitSetProperty(devices[ad].outputUnit_, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &(devices[ad].input), sizeof(AURenderCallbackStruct));
#endif

	if (err != noErr) {
		debug_msg("error AudioUnitSetProperty1 with error %ld: %s\n", err, GetMacOSStatusErrorString(err));
		return 0;
	}
	// Define the Mash stream description. Mash puts 20ms of data into each read
	// and write call. 20ms at 8000Hz equals 160 samples. Each sample is a u_char,
	// so that's 160 bytes. Mash uses 8-bit mu-law internally, so we need to convert
	// to 16-bit linear before using the audio data.
	devices[ad].mashStreamBasicDescription_.mSampleRate = 8000.0;
	//devices[ad].mashStreamBasicDescription_.mSampleRate = ifmt->sample_rate;
	devices[ad].mashStreamBasicDescription_.mFormatID = kAudioFormatLinearPCM;
#ifdef WORDS_BIGENDIAN
	devices[ad].mashStreamBasicDescription_.mFormatFlags =kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsBigEndian |kLinearPCMFormatFlagIsPacked;
#else
	devices[ad].mashStreamBasicDescription_.mFormatFlags =kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
#endif
	devices[ad].mashStreamBasicDescription_.mBytesPerPacket = 2;
	devices[ad].mashStreamBasicDescription_.mFramesPerPacket = 1;
	devices[ad].mashStreamBasicDescription_.mBytesPerFrame = 2;
	devices[ad].mashStreamBasicDescription_.mChannelsPerFrame = 1;
	devices[ad].mashStreamBasicDescription_.mBitsPerChannel = 16;

	// Inform the default output unit of our source format.
	err = AudioUnitSetProperty(devices[ad].outputUnit_, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &(devices[ad].mashStreamBasicDescription_), sizeof(AudioStreamBasicDescription));
	if (err != noErr) {
		debug_msg("error AudioUnitSetProperty2");
		printf("error setting output unit source format\n");
		return 0;
	}

	// check the stream format
	err = AudioUnitGetPropertyInfo(devices[ad].outputUnit_, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &propertySize, &writable);
	if (err != noErr) debug_msg("err getting propert info for kAudioUnitProperty_StreamFormat\n");

	err = AudioUnitGetProperty(devices[ad].outputUnit_, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamdesc_, &propertySize);
	if (err != noErr) debug_msg("err getting values for kAudioUnitProperty_StreamFormat\n");
	
	char name[128];
	audio_format_name(ifmt, name, 128);
	debug_msg("Requested ifmt %s\n",name);
	debug_msg("ifmt bytes pre block: %d\n",ifmt->bytes_per_block);

	// handle the requested format
	if (ifmt->encoding != DEV_S16) {
		audio_format_change_encoding(ifmt, DEV_S16);
		debug_msg("Requested ifmt changed to %s\n",name);
		debug_msg("ifmt bytes pre block: %d\n",ifmt->bytes_per_block);
	}

	audio_format_name(ofmt, name, 128);
	debug_msg("Requested ofmt %s\n",name);
	debug_msg("ofmt bytes pre block: %d\n",ofmt->bytes_per_block);
	
	// Allocate the read buffer and Z delay line.
	//readBufferSize_ = 8192;
	readBufferSize_ = ifmt->bytes_per_block * ringBufferFactor_;
	//readBufferSize_ = 320;
	//printf("readBufferSize_ %d\n", readBufferSize_);
	readBuffer_ = malloc(sizeof(u_char)*readBufferSize_);
	bzero(readBuffer_, readBufferSize_ * sizeof(u_char));
	//memset(readBuffer_, PCMU_AUDIO_ZERO, readBufferSize_);
	//inputReadIndex_ = -1; 
	inputReadIndex_ = 0; inputWriteIndex_ = 0;
	zLine_ = malloc(sizeof(double)*DECIM441_LENGTH / 80);
	availableInput_ = 0;

	// Allocate the write buffer.
	//writeBufferSize_ = 8000;
	writeBufferSize_ = ofmt->bytes_per_block * ringBufferFactor_;
	writeBuffer_ = malloc(sizeof(SInt16)*writeBufferSize_);
	bzero(writeBuffer_, writeBufferSize_ * sizeof(SInt16));
	outputReadIndex_ = 0; outputWriteIndex_ = 0;
	//outputWriteIndex_ = -1;
    	// Start audio processing.
	err = AudioUnitInitialize(devices[ad].outputUnit_);
	if (err != noErr) {
		debug_msg("error AudioUnitInitialize\n");
		return 0;
	}
	err = AudioDeviceStart(devices[ad].inputDeviceID_, audioIOProc);
	if (err != noErr) {
		fprintf(stderr, "Input device error: AudioDeviceStart\n");
		return 0;
	}
	err = AudioOutputUnitStart(devices[ad].outputUnit_);
	if (err != noErr) {
		fprintf(stderr, "Output device error: AudioOutputUnitStart\n");
		return 0;
	}
	// Inform the default output unit of our source format.
	/*
	err = AudioUnitSetProperty(devices[ad].outputUnit_, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &(devices[ad].mashStreamBasicDescription_), sizeof(AudioStreamBasicDescription));
	if (err != noErr) {
		debug_msg("error AudioUnitSetProperty3");
		return 0;
	}
	*/
	return 1;
};
Ejemplo n.º 19
0
void CoreAudioOutDriver::open(device_id_t device,
			      int sample_rate,
			      sample_format form,
			      int channels,
			      int num_samples,
			      int num_periods)
{
  if (this->is_open())
    throw std::logic_error("Device already open");


  if (form != SF_16LE)
    throw std::invalid_argument("Unknown sample format");

  m_impl->m_logger = logger;

  AudioDeviceID devid = GetDeviceID(logger, device);

  if (devid == kAudioDeviceUnknown)
    throw std::invalid_argument("Unknown device id");

  OSStatus err;
  const bool isInput = false;
  UInt32 propsize;
  
  AudioValueRange bufferRange;

  // check that the desired value is within the allowed range
  propsize = sizeof(bufferRange);
  err = AudioDeviceGetProperty(devid, 0, false,
			       kAudioDevicePropertyBufferFrameSizeRange,
			       &propsize,
			       &bufferRange);


  if (err != kAudioHardwareNoError)
    {
      throw std::runtime_error("Could not get buffer range");
    }

  propsize = sizeof(UInt32);
  UInt32 frames = my_min<int>(my_max<int>(num_samples,
					  (int) bufferRange.mMinimum),
			      (int) bufferRange.mMaximum);

  err = AudioDeviceSetProperty(devid, NULL, 0, isInput,
			       kAudioDevicePropertyBufferFrameSize,
			       propsize, &frames);
    
  if (err != kAudioHardwareNoError)
    {
      throw std::runtime_error("Could not set buffer size");
    }


  propsize = sizeof(frames);
  err = AudioDeviceGetProperty(devid, 0, isInput,
			       kAudioDevicePropertyBufferFrameSize,
			       &propsize, &frames);
    
  if (err != kAudioHardwareNoError)
    {
      throw std::runtime_error("Could not read buffer size");
    }

  char bbc[256] = {0};
  sprintf(bbc, "Buffer size in frames: %i", frames);
  logger(2, bbc);

  Float64 sampleRate = sample_rate;
  propsize = sizeof(sampleRate);
  err = AudioDeviceSetProperty(devid, NULL, 0, isInput,
			       kAudioDevicePropertyNominalSampleRate,
			       propsize, &sampleRate);
    
  if (err != kAudioHardwareNoError)
    {
      throw std::runtime_error("Could not set sample rate");
    }

  print_info(devid, logger, isInput);

  propsize = sizeof(m_impl->m_format);
  err = AudioDeviceGetProperty(devid, 0, isInput,
			       kAudioDevicePropertyStreamFormat,
			       &propsize,
			       &m_impl->m_format);

  if (err != kAudioHardwareNoError)
    {
      throw std::runtime_error("Could not get audio format");
    }


  // Desired format
  memset(&m_impl->m_input_format, 0, sizeof(m_impl->m_input_format));
  

  // set channels, format to SF_16LE

  m_impl->m_input_format.mSampleRate       = sample_rate;
  m_impl->m_input_format.mFormatID         = kAudioFormatLinearPCM;
  m_impl->m_input_format.mFormatFlags
         = kLinearPCMFormatFlagIsSignedInteger |
           kLinearPCMFormatFlagIsPacked;

  m_impl->m_input_format.mBytesPerPacket   = 2*channels;
  m_impl->m_input_format.mFramesPerPacket  = 1;
  m_impl->m_input_format.mBytesPerFrame    = m_impl->m_input_format.mBytesPerPacket;
  m_impl->m_input_format.mChannelsPerFrame = channels;
  m_impl->m_input_format.mBitsPerChannel   = 16;

#define USE_COMPLEX_AUDIO_CONVERTER
  //#define USE_SIMPLE_AUDIO_CONVERTER

#if defined(USE_SIMPLE_AUDIO_CONVERTER)
  m_impl->m_converter = new SimpleConverter(m_impl->m_input_format,
					    m_impl->m_format);
#elif defined (USE_COMPLEX_AUDIO_CONVERTER)
  m_impl->m_converter = new ComplexConverter(m_impl->m_input_format,
					     m_impl->m_format);
#else
    // TODO: this works only for 2 channels float to 1 channel mono 16LE!
  m_impl->m_converter = new Mono16LEPCMToStereoFloat;
#endif

  print_format pf1(logger, "Device Format\n");
  pf1(m_impl->m_format);

  print_format pf2(logger, "Input Format\n");
  pf2(m_impl->m_input_format);

  // Set the buffer latency (audio output is only started after
  // the buffer contains m_min_buffer samples).
  m_impl->m_min_buffer = num_samples*num_periods;
  m_impl->m_ID = devid;

  AudioDeviceAddIOProc(devid, Impl::OutputIOProc, m_impl.get());
}
Ejemplo n.º 20
0
static AUDIO_OUT *
macosx_open (int channels, int samplerate)
{	MACOSX_AUDIO_OUT *macosx_out ;
	OSStatus	err ;
	size_t 		count ;

	if ((macosx_out = malloc (sizeof (MACOSX_AUDIO_OUT))) == NULL)
	{	perror ("macosx_open : malloc ") ;
		exit (1) ;
		} ;

	macosx_out->magic = MACOSX_MAGIC ;
	macosx_out->channels = channels ;
	macosx_out->samplerate = samplerate ;

	macosx_out->device = kAudioDeviceUnknown ;

	/*  get the default output device for the HAL */
	count = sizeof (AudioDeviceID) ;
	if ((err = AudioHardwareGetProperty (kAudioHardwarePropertyDefaultOutputDevice,
				&count, (void *) &(macosx_out->device))) != noErr)
	{	printf ("AudioHardwareGetProperty failed.\n") ;
		free (macosx_out) ;
		return NULL ;
		} ;

	/*  get the buffersize that the default device uses for IO */
	count = sizeof (UInt32) ;
	if ((err = AudioDeviceGetProperty (macosx_out->device, 0, false, kAudioDevicePropertyBufferSize,
				&count, &(macosx_out->buffer_size))) != noErr)
	{	printf ("AudioDeviceGetProperty (AudioDeviceGetProperty) failed.\n") ;
		free (macosx_out) ;
		return NULL ;
		} ;

	/*  get a description of the data format used by the default device */
	count = sizeof (AudioStreamBasicDescription) ;
	if ((err = AudioDeviceGetProperty (macosx_out->device, 0, false, kAudioDevicePropertyStreamFormat,
				&count, &(macosx_out->format))) != noErr)
	{	printf ("AudioDeviceGetProperty (kAudioDevicePropertyStreamFormat) failed.\n") ;
		free (macosx_out) ;
		return NULL ;
		} ;

	macosx_out->format.mSampleRate = samplerate ;
	macosx_out->format.mChannelsPerFrame = channels ;

	if ((err = AudioDeviceSetProperty (macosx_out->device, NULL, 0, false, kAudioDevicePropertyStreamFormat,
				sizeof (AudioStreamBasicDescription), &(macosx_out->format))) != noErr)
	{	printf ("AudioDeviceSetProperty (kAudioDevicePropertyStreamFormat) failed.\n") ;
		free (macosx_out) ;
		return NULL ;
		} ;

	/*  we want linear pcm */
	if (macosx_out->format.mFormatID != kAudioFormatLinearPCM)
	{	free (macosx_out) ;
		return NULL ;
		} ;

	macosx_out->done_playing = 0 ;

	/* Fire off the device. */
	if ((err = AudioDeviceAddIOProc (macosx_out->device, macosx_audio_out_callback,
			(void *) macosx_out)) != noErr)
	{	printf ("AudioDeviceAddIOProc failed.\n") ;
		free (macosx_out) ;
		return NULL ;
		} ;

	return (MACOSX_AUDIO_OUT *) macosx_out ;
} /* macosx_open */
Ejemplo n.º 21
0
static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
                           PaStream** s,
                           const PaStreamParameters *inputParameters,
                           const PaStreamParameters *outputParameters,
                           double sampleRate,
                           unsigned long framesPerBuffer,
                           PaStreamFlags streamFlags,
                           PaStreamCallback *streamCallback,
                           void *userData )
{
    PaError err = paNoError;
    PaMacCoreHostApiRepresentation *macCoreHostApi = (PaMacCoreHostApiRepresentation *)hostApi;
    PaMacCoreStream *stream = PaUtil_AllocateMemory(sizeof(PaMacCoreStream));
    stream->isActive = 0;
    stream->isStopped = 1;
    stream->inputDevice = kAudioDeviceUnknown;
    stream->outputDevice = kAudioDeviceUnknown;
    
    PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
                                           ( (streamCallback)
                                             ? &macCoreHostApi->callbackStreamInterface
                                             : &macCoreHostApi->blockingStreamInterface ),
                                           streamCallback, userData );
    PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate );
    
    *s = (PaStream*)stream;
    PaMacClientData *clientData = PaUtil_AllocateMemory(sizeof(PaMacClientData));
    clientData->stream = stream;
    clientData->callback = streamCallback;
    clientData->userData = userData;
    clientData->inputBuffer = 0;
    clientData->outputBuffer = 0;
    clientData->ditherGenerator = PaUtil_AllocateMemory(sizeof(PaUtilTriangularDitherGenerator));
    PaUtil_InitializeTriangularDitherState(clientData->ditherGenerator);
    
    if (inputParameters != NULL) {
        stream->inputDevice = macCoreHostApi->macCoreDeviceIds[inputParameters->device];
        clientData->inputConverter = PaUtil_SelectConverter(paFloat32, inputParameters->sampleFormat, streamFlags);
        clientData->inputBuffer = PaUtil_AllocateMemory(Pa_GetSampleSize(inputParameters->sampleFormat) * framesPerBuffer * inputParameters->channelCount);
        clientData->inputChannelCount = inputParameters->channelCount;
        clientData->inputSampleFormat = inputParameters->sampleFormat;
        err = SetUpUnidirectionalStream(stream->inputDevice, sampleRate, framesPerBuffer, 1);
    }
    
    if (err == paNoError && outputParameters != NULL) {
        stream->outputDevice = macCoreHostApi->macCoreDeviceIds[outputParameters->device];
        clientData->outputConverter = PaUtil_SelectConverter(outputParameters->sampleFormat, paFloat32, streamFlags);
        clientData->outputBuffer = PaUtil_AllocateMemory(Pa_GetSampleSize(outputParameters->sampleFormat) * framesPerBuffer * outputParameters->channelCount);
        clientData->outputChannelCount = outputParameters->channelCount;
        clientData->outputSampleFormat = outputParameters->sampleFormat;
        err = SetUpUnidirectionalStream(stream->outputDevice, sampleRate, framesPerBuffer, 0);
    }

    if (inputParameters == NULL || outputParameters == NULL || stream->inputDevice == stream->outputDevice) {
        AudioDeviceID device = (inputParameters == NULL) ? stream->outputDevice : stream->inputDevice;

        AudioDeviceAddIOProc(device, AudioIOProc, clientData);
    }
    else {
        // using different devices for input and output
        AudioDeviceAddIOProc(stream->inputDevice, AudioInputProc, clientData);
        AudioDeviceAddIOProc(stream->outputDevice, AudioOutputProc, clientData);
    }
    
    return err;
}
Ejemplo n.º 22
0
// Initialize the BlockSound class
BlockSound::BlockSound() {
	sample_size = 0;

#ifdef __APPLE__
	remaining = 0;

	UInt32 size = sizeof(device);

	if (AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice,
				&size, (void *)&device) != noErr) return;

	size = sizeof(format);
	if (AudioDeviceGetProperty(device, 0, false, kAudioDevicePropertyStreamFormat,
				&size, &format) != noErr) return;

	// Set up a format we like...
	format.mSampleRate       = 44100.0;	// 44.1kHz
	format.mChannelsPerFrame = 2;		// stereo

	if (AudioDeviceSetProperty(device, NULL, 0, false,
				kAudioDevicePropertyStreamFormat,
				sizeof(format), &format) != noErr) return;

	// Check we got linear pcm - what to do if we did not ???
	if (format.mFormatID != kAudioFormatLinearPCM) return;

	// Attach the callback and start the device
#  if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
	if (AudioDeviceCreateIOProcID(device, audio_cb, (void *)this, &audio_proc_id) != noErr) return;
	AudioDeviceStart(device, audio_proc_id);
#  else
	if (AudioDeviceAddIOProc(device, audio_cb, (void *)this) != noErr) return;
	AudioDeviceStart(device, audio_cb);
#  endif

	sample_size = (int)format.mSampleRate;

#elif defined(WIN32)
	WAVEFORMATEX	format;

	memset(&format, 0, sizeof(format));
	format.cbSize          = sizeof(format);
	format.wFormatTag      = WAVE_FORMAT_PCM;
	format.nChannels       = 2;
	format.nSamplesPerSec  = 44100;
	format.nAvgBytesPerSec = 44100 * 4;
	format.nBlockAlign     = 4;
	format.wBitsPerSample  = 16;

	data_handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, format.nSamplesPerSec * 4);
	if (!data_handle) return;

	data_ptr = (LPSTR)GlobalLock(data_handle);

	header_handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, sizeof(WAVEHDR));
	if (!header_handle) return;

	header_ptr = (WAVEHDR *)GlobalLock(header_handle);

	header_ptr->lpData  = data_ptr;
	header_ptr->dwFlags = 0;
	header_ptr->dwLoops = 0;

	if (waveOutOpen(&device, WAVE_MAPPER, &format, 0, 0, WAVE_ALLOWSYNC)
			!= MMSYSERR_NOERROR) return;

	sample_size = format.nSamplesPerSec;

#else
#  ifdef HAVE_ALSA_ASOUNDLIB_H
	handle = NULL;

	if (snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0) >= 0) {
		// Initialize PCM sound stuff...
		snd_pcm_hw_params_t *params;

		snd_pcm_hw_params_alloca(&params);
		snd_pcm_hw_params_any(handle, params);
		snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
		snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16);
		snd_pcm_hw_params_set_channels(handle, params, 2);
		unsigned rate = 44100;
		int dir;
		snd_pcm_hw_params_set_rate_near(handle, params, &rate, &dir);
		snd_pcm_uframes_t period = (int)rate;
		snd_pcm_hw_params_set_period_size_near(handle, params, &period, &dir);

		sample_size = rate;

		if (snd_pcm_hw_params(handle, params) < 0) {
			sample_size = 0;
			snd_pcm_close(handle);
			handle = NULL;
		}
	}
#  endif // HAVE_ALSA_ASOUNDLIB_H
#endif // __APPLE__

	if (sample_size) {
		// Make an explosion sound by passing white noise through a low pass
		// filter with a decreasing frequency...
		sample_data = new short[2 * sample_size];

		short *sample_ptr = sample_data;
		int max_sample = 2 * sample_size - 2;

		*sample_ptr++ = 0;
		*sample_ptr++ = 0;

		for (int j = max_sample; j > 0; j --, sample_ptr ++) {
			float freq = (float)j / (float)max_sample;
			float volume = 32767.0 * (0.5 * sqrt(freq) + 0.5);
			float sample = 0.0001 * ((rand() % 20001) - 10000);

			*sample_ptr = (int)(volume * freq * sample +
					(1.0 - freq) * sample_ptr[-2]);
		}
	}
}
Ejemplo n.º 23
0
SndCoreAudio::SndCoreAudio(int channels,int bufframes, int buffnos, float norm, SndObj** inObjs, 
                 AudioDeviceID dev,  int vecsize, float sr):
                  SndIO((channels < 2 ?  2 : channels), sizeof(float)*8, inObjs, vecsize, sr) {
                  
UInt32 psize;
int i;
UInt32 obufframes, ibufframes;
AudioStreamBasicDescription format;
m_norm = norm ? norm : 1.f;

if(dev=DEV_DEFAULT){
psize = sizeof(AudioDeviceID);
AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice,
                     &psize, &m_dev);
}
else m_dev = dev;

m_bufframes = bufframes;
m_buffsize = bufframes*sizeof(float)*m_channels;
m_buffitems = bufframes*m_channels;
m_buffnos = buffnos;

psize = 4;
// set the buffer size
// output
AudioDeviceSetProperty(m_dev,NULL,0,false,
            kAudioDevicePropertyBufferFrameSize,
            psize, &m_bufframes);
// input            
AudioDeviceSetProperty(m_dev,NULL,0,true,
            kAudioDevicePropertyBufferFrameSize,
            psize, &m_bufframes);
            
// check that it matches the expected size
AudioDeviceGetProperty(m_dev,0,true,
            kAudioDevicePropertyBufferFrameSize,
            &psize, &ibufframes);
            
AudioDeviceGetProperty(m_dev,0,false,
            kAudioDevicePropertyBufferFrameSize,
            &psize, &obufframes);
                                    
if(ibufframes != m_bufframes){            
    
    if(ibufframes == obufframes)
    m_bufframes = obufframes;
    else {
    m_error = 21;
    return;
    }
    
}

   m_format.mSampleRate = m_sr;
   m_format.mFormatID = kAudioFormatLinearPCM;
   m_format.mFormatFlags = kAudioFormatFlagIsFloat;
   m_format.mBytesPerPacket = sizeof(float)*m_channels;
   m_format.mFramesPerPacket = 1;
   m_format.mBytesPerFrame = format.mBytesPerPacket;
   m_format.mChannelsPerFrame = m_channels;
   m_format.mBitsPerChannel = sizeof(float);

psize = sizeof(AudioStreamBasicDescription);

AudioDeviceSetProperty(m_dev,NULL,0,true,      
     kAudioDevicePropertyStreamFormat,
     psize, &m_format);

AudioDeviceSetProperty(m_dev,NULL,0,false,      
     kAudioDevicePropertyStreamFormat,
     psize, &m_format);

AudioDeviceGetProperty(m_dev,0,false,      
     kAudioDevicePropertyStreamFormat,
     &psize, &format);

if(format.mSampleRate != m_sr){
    
       m_error = 22;
     return;         
}

if(format.mChannelsPerFrame != m_channels){
    
     m_error = 23;
     return;         
}

m_outbuffs = new float*[m_buffnos];
m_inbuffs = new float*[m_buffnos];
m_inused = new bool[m_buffnos];
m_outused = new bool[m_buffnos];

for(i=0; i < m_buffnos; i++){

if(!(m_inbuffs[i] = new float[m_bufframes*m_channels])){
m_error = 24;
return;
}
if(!(m_outbuffs[i] = new float[m_bufframes*m_channels])){
m_error = 25;
return;
}
m_inused[i] = m_outused[i] = true;
}

m_incurbuff = m_outcurbuff = m_iocurbuff = 0;
m_incount = m_outcount = 0;

AudioDeviceAddIOProc(m_dev, SndObj_IOProcEntry, this);
AudioDeviceStart(m_dev, SndObj_IOProcEntry);
}
Ejemplo n.º 24
0
static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
                              void *drv_opaque)
{
    OSStatus status;
    coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
    UInt32 propertySize;
    int err;
    const char *typ = "playback";
    AudioValueRange frameRange;
    CoreaudioConf *conf = drv_opaque;

    /* create mutex */
    err = pthread_mutex_init(&core->mutex, NULL);
    if (err) {
        dolog("Could not create mutex\nReason: %s\n", strerror (err));
        return -1;
    }

    audio_pcm_init_info (&hw->info, as);

    /* open default output device */
    propertySize = sizeof(core->outputDeviceID);
    status = AudioHardwareGetProperty(
        kAudioHardwarePropertyDefaultOutputDevice,
        &propertySize,
        &core->outputDeviceID);
    if (status != kAudioHardwareNoError) {
        coreaudio_logerr2 (status, typ,
                           "Could not get default output Device\n");
        return -1;
    }
    if (core->outputDeviceID == kAudioDeviceUnknown) {
        dolog ("Could not initialize %s - Unknown Audiodevice\n", typ);
        return -1;
    }

    /* get minimum and maximum buffer frame sizes */
    propertySize = sizeof(frameRange);
    status = AudioDeviceGetProperty(
        core->outputDeviceID,
        0,
        0,
        kAudioDevicePropertyBufferFrameSizeRange,
        &propertySize,
        &frameRange);
    if (status != kAudioHardwareNoError) {
        coreaudio_logerr2 (status, typ,
                           "Could not get device buffer frame range\n");
        return -1;
    }

    if (frameRange.mMinimum > conf->buffer_frames) {
        core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMinimum;
        dolog ("warning: Upsizing Buffer Frames to %f\n", frameRange.mMinimum);
    }
    else if (frameRange.mMaximum < conf->buffer_frames) {
        core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMaximum;
        dolog ("warning: Downsizing Buffer Frames to %f\n", frameRange.mMaximum);
    }
    else {
        core->audioDevicePropertyBufferFrameSize = conf->buffer_frames;
    }

    /* set Buffer Frame Size */
    propertySize = sizeof(core->audioDevicePropertyBufferFrameSize);
    status = AudioDeviceSetProperty(
        core->outputDeviceID,
        NULL,
        0,
        false,
        kAudioDevicePropertyBufferFrameSize,
        propertySize,
        &core->audioDevicePropertyBufferFrameSize);
    if (status != kAudioHardwareNoError) {
        coreaudio_logerr2 (status, typ,
                           "Could not set device buffer frame size %" PRIu32 "\n",
                           (uint32_t)core->audioDevicePropertyBufferFrameSize);
        return -1;
    }

    /* get Buffer Frame Size */
    propertySize = sizeof(core->audioDevicePropertyBufferFrameSize);
    status = AudioDeviceGetProperty(
        core->outputDeviceID,
        0,
        false,
        kAudioDevicePropertyBufferFrameSize,
        &propertySize,
        &core->audioDevicePropertyBufferFrameSize);
    if (status != kAudioHardwareNoError) {
        coreaudio_logerr2 (status, typ,
                           "Could not get device buffer frame size\n");
        return -1;
    }
    hw->samples = conf->nbuffers * core->audioDevicePropertyBufferFrameSize;

    /* get StreamFormat */
    propertySize = sizeof(core->outputStreamBasicDescription);
    status = AudioDeviceGetProperty(
        core->outputDeviceID,
        0,
        false,
        kAudioDevicePropertyStreamFormat,
        &propertySize,
        &core->outputStreamBasicDescription);
    if (status != kAudioHardwareNoError) {
        coreaudio_logerr2 (status, typ,
                           "Could not get Device Stream properties\n");
        core->outputDeviceID = kAudioDeviceUnknown;
        return -1;
    }

    /* set Samplerate */
    core->outputStreamBasicDescription.mSampleRate = (Float64) as->freq;
    propertySize = sizeof(core->outputStreamBasicDescription);
    status = AudioDeviceSetProperty(
        core->outputDeviceID,
        0,
        0,
        0,
        kAudioDevicePropertyStreamFormat,
        propertySize,
        &core->outputStreamBasicDescription);
    if (status != kAudioHardwareNoError) {
        coreaudio_logerr2 (status, typ, "Could not set samplerate %d\n",
                           as->freq);
        core->outputDeviceID = kAudioDeviceUnknown;
        return -1;
    }

    /* set Callback */
    status = AudioDeviceAddIOProc(core->outputDeviceID, audioDeviceIOProc, hw);
    if (status != kAudioHardwareNoError) {
        coreaudio_logerr2 (status, typ, "Could not set IOProc\n");
        core->outputDeviceID = kAudioDeviceUnknown;
        return -1;
    }

    /* start Playback */
    if (!isPlaying(core->outputDeviceID)) {
        status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc);
        if (status != kAudioHardwareNoError) {
            coreaudio_logerr2 (status, typ, "Could not start playback\n");
            AudioDeviceRemoveIOProc(core->outputDeviceID, audioDeviceIOProc);
            core->outputDeviceID = kAudioDeviceUnknown;
            return -1;
        }
    }

    return 0;
}
Ejemplo n.º 25
0
static int
coreaudio_voice_init (coreaudioVoice*    core,
                      struct audsettings*  as,
                      int                frameSize,
                      AudioDeviceIOProc  ioproc,
                      void*              hw,
                      int                input)
{
    OSStatus  status;
    UInt32    propertySize;
    int       err;
    int       bits = 8;
    AudioValueRange frameRange;
    const char*  typ = input ? "input" : "playback";

    core->isInput = input ? true : false;

    /* create mutex */
    err = pthread_mutex_init(&core->mutex, NULL);
    if (err) {
        dolog("Could not create mutex\nReason: %s\n", strerror (err));
        return -1;
    }

    if (as->fmt == AUD_FMT_S16 || as->fmt == AUD_FMT_U16) {
        bits = 16;
    }

    // TODO: audio_pcm_init_info (&hw->info, as);
    /* open default output device */
   /* note: we use DefaultSystemOutputDevice because DefaultOutputDevice seems to
    * always link to the internal speakers, and not the ones selected through system properties
    * go figure...
    */
    propertySize = sizeof(core->deviceID);
    status = AudioHardwareGetProperty(
        input ? kAudioHardwarePropertyDefaultInputDevice :
                kAudioHardwarePropertyDefaultSystemOutputDevice,
        &propertySize,
        &core->deviceID);
    if (status != kAudioHardwareNoError) {
        coreaudio_logerr2 (status, typ,
                           "Could not get default %s device\n", typ);
        return -1;
    }
    if (core->deviceID == kAudioDeviceUnknown) {
        dolog ("Could not initialize %s - Unknown Audiodevice\n", typ);
        return -1;
    }

    /* get minimum and maximum buffer frame sizes */
    propertySize = sizeof(frameRange);
    status = AudioDeviceGetProperty(
        core->deviceID,
        0,
        core->isInput,
        kAudioDevicePropertyBufferFrameSizeRange,
        &propertySize,
        &frameRange);
    if (status != kAudioHardwareNoError) {
        coreaudio_logerr2 (status, typ,
                           "Could not get device buffer frame range\n");
        return -1;
    }

    if (frameRange.mMinimum > frameSize) {
        core->bufferFrameSize = (UInt32) frameRange.mMinimum;
        dolog ("warning: Upsizing Output Buffer Frames to %f\n", frameRange.mMinimum);
    }
    else if (frameRange.mMaximum < frameSize) {
        core->bufferFrameSize = (UInt32) frameRange.mMaximum;
        dolog ("warning: Downsizing Output Buffer Frames to %f\n", frameRange.mMaximum);
    }
    else {
        core->bufferFrameSize = frameSize;
    }

    /* set Buffer Frame Size */
    propertySize = sizeof(core->bufferFrameSize);
    status = AudioDeviceSetProperty(
        core->deviceID,
        NULL,
        0,
        core->isInput,
        kAudioDevicePropertyBufferFrameSize,
        propertySize,
        &core->bufferFrameSize);
    if (status != kAudioHardwareNoError) {
        coreaudio_logerr2 (status, typ,
                           "Could not set device buffer frame size %ld\n",
                           core->bufferFrameSize);
        return -1;
    }

    /* get Buffer Frame Size */
    propertySize = sizeof(core->bufferFrameSize);
    status = AudioDeviceGetProperty(
        core->deviceID,
        0,
        core->isInput,
        kAudioDevicePropertyBufferFrameSize,
        &propertySize,
        &core->bufferFrameSize);
    if (status != kAudioHardwareNoError) {
        coreaudio_logerr2 (status, typ,
                           "Could not get device buffer frame size\n");
        return -1;
    }
    // TODO: hw->samples = *pNBuffers * core->bufferFrameSize;

    /* get StreamFormat */
    propertySize = sizeof(core->streamBasicDescription);
    status = AudioDeviceGetProperty(
        core->deviceID,
        0,
        core->isInput,
        kAudioDevicePropertyStreamFormat,
        &propertySize,
        &core->streamBasicDescription);
    if (status != kAudioHardwareNoError) {
        coreaudio_logerr2 (status, typ,
                           "Could not get Device Stream properties\n");
        core->deviceID = kAudioDeviceUnknown;
        return -1;
    }

    /* set Samplerate */
    core->streamBasicDescription.mSampleRate = (Float64) as->freq;
    propertySize = sizeof(core->streamBasicDescription);
    status = AudioDeviceSetProperty(
        core->deviceID,
        0,
        0,
        core->isInput,
        kAudioDevicePropertyStreamFormat,
        propertySize,
        &core->streamBasicDescription);
    if (status != kAudioHardwareNoError) {
        coreaudio_logerr2 (status, typ, "Could not set samplerate %d\n",
                           as->freq);
        core->deviceID = kAudioDeviceUnknown;
        return -1;
    }

    /* set Callback */
    core->ioproc = ioproc;
    status = AudioDeviceAddIOProc(core->deviceID, ioproc, hw);
    if (status != kAudioHardwareNoError) {
        coreaudio_logerr2 (status, typ, "Could not set IOProc\n");
        core->deviceID = kAudioDeviceUnknown;
        return -1;
    }

    /* start Playback */
    if (!input && !coreaudio_voice_isPlaying(core)) {
        status = AudioDeviceStart(core->deviceID, core->ioproc);
        if (status != kAudioHardwareNoError) {
            coreaudio_logerr2 (status, typ, "Could not start playback\n");
            AudioDeviceRemoveIOProc(core->deviceID, core->ioproc);
            core->deviceID = kAudioDeviceUnknown;
            return -1;
        }
    }

    return 0;
}
Ejemplo n.º 26
0
static void
macosx_play (int argc, char *argv [])
{	MacOSXAudioData 	audio_data ;
	OSStatus	err ;
	UInt32		count, buffer_size ;
	int 		k ;

	audio_data.fake_stereo = 0 ;
	audio_data.device = kAudioDeviceUnknown ;

	/*  get the default output device for the HAL */
	count = sizeof (AudioDeviceID) ;
	if ((err = AudioHardwareGetProperty (kAudioHardwarePropertyDefaultOutputDevice,
				&count, (void *) &(audio_data.device))) != noErr)
	{	printf ("AudioHardwareGetProperty (kAudioDevicePropertyDefaultOutputDevice) failed.\n") ;
		return ;
		} ;

	/*  get the buffersize that the default device uses for IO */
	count = sizeof (UInt32) ;
	if ((err = AudioDeviceGetProperty (audio_data.device, 0, false, kAudioDevicePropertyBufferSize,
				&count, &buffer_size)) != noErr)
	{	printf ("AudioDeviceGetProperty (kAudioDevicePropertyBufferSize) failed.\n") ;
		return ;
		} ;

	/*  get a description of the data format used by the default device */
	count = sizeof (AudioStreamBasicDescription) ;
	if ((err = AudioDeviceGetProperty (audio_data.device, 0, false, kAudioDevicePropertyStreamFormat,
				&count, &(audio_data.format))) != noErr)
	{	printf ("AudioDeviceGetProperty (kAudioDevicePropertyStreamFormat) failed.\n") ;
		return ;
		} ;

	/* Base setup completed. Now play files. */
	for (k = 1 ; k < argc ; k++)
	{	printf ("Playing %s\n", argv [k]) ;
		if (! (audio_data.sndfile = sf_open (argv [k], SFM_READ, &(audio_data.sfinfo))))
		{	puts (sf_strerror (NULL)) ;
			continue ;
			} ;

		if (audio_data.sfinfo.channels < 1 || audio_data.sfinfo.channels > 2)
		{	printf ("Error : channels = %d.\n", audio_data.sfinfo.channels) ;
			continue ;
			} ;

		audio_data.format.mSampleRate = audio_data.sfinfo.samplerate ;

		if (audio_data.sfinfo.channels == 1)
		{	audio_data.format.mChannelsPerFrame = 2 ;
			audio_data.fake_stereo = 1 ;
			}
		else
		audio_data.format.mChannelsPerFrame = audio_data.sfinfo.channels ;

		if ((err = AudioDeviceSetProperty (audio_data.device, NULL, 0, false, kAudioDevicePropertyStreamFormat,
					sizeof (AudioStreamBasicDescription), &(audio_data.format))) != noErr)
		{	printf ("AudioDeviceSetProperty (kAudioDevicePropertyStreamFormat) failed.\n") ;
			return ;
			} ;

		/*  we want linear pcm */
		if (audio_data.format.mFormatID != kAudioFormatLinearPCM)
			return ;

		/* Fire off the device. */
		if ((err = AudioDeviceAddIOProc (audio_data.device, macosx_audio_out_callback,
				(void *) &audio_data)) != noErr)
		{	printf ("AudioDeviceAddIOProc failed.\n") ;
			return ;
			} ;

		err = AudioDeviceStart (audio_data.device, macosx_audio_out_callback) ;
		if	(err != noErr)
			return ;

		audio_data.done_playing = SF_FALSE ;

		while (audio_data.done_playing == SF_FALSE)
			usleep (10 * 1000) ; /* 10 000 milliseconds. */

		if ((err = AudioDeviceStop (audio_data.device, macosx_audio_out_callback)) != noErr)
		{	printf ("AudioDeviceStop failed.\n") ;
			return ;
			} ;

		err = AudioDeviceRemoveIOProc (audio_data.device, macosx_audio_out_callback) ;
		if (err != noErr)
		{	printf ("AudioDeviceRemoveIOProc failed.\n") ;
			return ;
			} ;

		sf_close (audio_data.sndfile) ;
		} ;

	return ;
} /* macosx_play */
Ejemplo n.º 27
0
static int audio_init(error_t *error) {
  UInt32 size;
  int ret;
  AudioStreamBasicDescription format;
  UInt32 byte_count;

  /* get device */
  size = sizeof(audio.device);
  ret = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice,
                                 &size, &audio.device);
  if (ret != 0) {
    error_set(error, "Could not get default audio device");
    return 0;
  }
  if (audio.device == kAudioDeviceUnknown) {
    error_set(error, "Unknown audio device");
    return 0;
  }

  /* check that the format is pcm */
  size = sizeof(format);
  ret = AudioDeviceGetProperty(audio.device, 0, false,
                               kAudioDevicePropertyStreamFormat,
                               &size, &format);
  if (ret != 0) {
    error_set(error, "Could not get the stream format");
    return 0;
  }
  if (format.mFormatID != kAudioFormatLinearPCM) {
    error_set(error, "The output device is not using PCM format");
    return 0;
  }

  /* set the buffer size, channels, samplerate */
  /* XXX channels, samplerate */
  size = sizeof(byte_count);
  ret = AudioDeviceGetProperty(audio.device, 0, false,
                               kAudioDevicePropertyBufferSize,
                               &size, &byte_count);
  if (ret) {
    error_set(error, "Could not get the buffer size");
    return 0;
  }
  byte_count = 1152 * 2 * sizeof(float);
  ret = AudioDeviceSetProperty(audio.device, NULL, 0, false,
                               kAudioDevicePropertyBufferSize,
                               size, &byte_count);
  if (ret) {
    error_set(error, "Could not set the buffer size");
    return 0;
  }

  /* initialize the ring buffer */
  rb_init(&audio.rb);
  
  ret = AudioDeviceAddIOProc(audio.device, audio_play_proc, NULL);
  if (ret) {
    error_set(error, "Could not start the IO proc");
    return 0;
  }

  audio_initialized = 1;

  return 1;
}
Ejemplo n.º 28
0
/*
==========
idAudioHardwareOSX::Initialize
==========
*/
bool idAudioHardwareOSX::Initialize( )
{

    UInt32			size;
    OSStatus		status;
    int				i, deviceCount;
    AudioDeviceID	*deviceList;
    char			buf[ 1024 ];

    status = AudioHardwareGetPropertyInfo( kAudioHardwarePropertyDevices, &size, NULL );
    if ( status != kAudioHardwareNoError )
    {
        common->Warning( "AudioHardwareGetPropertyInfo kAudioHardwarePropertyDevices failed. status: %s", ExtractStatus( status ) );
        InitFailed();
        return false;
    }

    deviceCount = size / sizeof( AudioDeviceID );
    if ( !deviceCount )
    {
        common->Printf( "No sound device found\n" );
        InitFailed();
        return false;
    }

    deviceList = (AudioDeviceID*)malloc( size );
    status = AudioHardwareGetProperty( kAudioHardwarePropertyDevices, &size, deviceList );
    if ( status != kAudioHardwareNoError )
    {
        common->Warning( "AudioHardwareGetProperty kAudioHardwarePropertyDevices failed. status: %s", ExtractStatus( status ) );
        free( deviceList );
        InitFailed();
        return false;
    }

    common->Printf( "%d sound device(s)\n", deviceCount );
    for( i = 0; i < deviceCount; i++ )
    {
        size = 1024;
        status = AudioDeviceGetProperty( deviceList[ i ], 0, false, kAudioDevicePropertyDeviceName, &size, buf );
        if ( status != kAudioHardwareNoError )
        {
            common->Warning( "AudioDeviceGetProperty kAudioDevicePropertyDeviceName %d failed. status: %s", i, ExtractStatus( status ) );
            free( deviceList );
            InitFailed();
            return false;
        }
        common->Printf( "  %d: ID %d, %s - ", i, deviceList[ i ], buf );
        size = 1024;
        status = AudioDeviceGetProperty( deviceList[ i ], 0, false, kAudioDevicePropertyDeviceManufacturer, &size, buf );
        if ( status != kAudioHardwareNoError )
        {
            common->Warning( "AudioDeviceGetProperty kAudioDevicePropertyDeviceManufacturer %d failed. status: %s", i, ExtractStatus( status ) );
            free( deviceList );
            InitFailed();
            return false;
        }
        common->Printf( "%s\n", buf );
    }

    if ( s_device.GetInteger() != -1 && s_device.GetInteger() < deviceCount )
    {
        selectedDevice = deviceList[ s_device.GetInteger() ];
        common->Printf( "s_device: device ID %d\n", selectedDevice );
    }
    else
    {
        size = sizeof( selectedDevice );
        status = AudioHardwareGetProperty( kAudioHardwarePropertyDefaultOutputDevice, &size, &selectedDevice );
        if ( status != kAudioHardwareNoError )
        {
            common->Warning( "AudioHardwareGetProperty kAudioHardwarePropertyDefaultOutputDevice failed. status: %s", ExtractStatus( status ) );

            free( deviceList );
            InitFailed();
            return false;
        }
        common->Printf( "select default device, ID %d\n", selectedDevice );
    }

    free( deviceList );
    deviceList = NULL;

    /*
    // setup a listener to watch for changes to properties
    status = AudioDeviceAddPropertyListener( selectedDevice, 0, false, kAudioDeviceProcessorOverload, DeviceListener, this );
    if ( status != kAudioHardwareNoError ) {
    	common->Warning( "AudioDeviceAddPropertyListener kAudioDeviceProcessorOverload failed. status: %s", ExtractStatus( status ) );
    	InitFailed();
    	return;
    }
    */

    Float64 sampleRate;
    size = sizeof( sampleRate );
    status = AudioDeviceGetProperty( selectedDevice, 0, false, kAudioDevicePropertyNominalSampleRate, &size, &sampleRate );
    if ( status != kAudioHardwareNoError )
    {
        common->Warning( "AudioDeviceGetProperty %d kAudioDevicePropertyNominalSampleRate failed. status: %s", selectedDevice, ExtractStatus( status ) );
        InitFailed();
        return false;
    }
    common->Printf( "current nominal rate: %g\n", sampleRate );

    if ( sampleRate != PRIMARYFREQ )
    {

        GetAvailableNominalSampleRates();

        sampleRate = PRIMARYFREQ;
        common->Printf( "setting rate to: %g\n", sampleRate );
        status = AudioDeviceSetProperty( selectedDevice, NULL, 0, false, kAudioDevicePropertyNominalSampleRate, size, &sampleRate );
        if ( status != kAudioHardwareNoError )
        {
            common->Warning( "AudioDeviceSetProperty %d kAudioDevicePropertyNominalSampleRate %g failed. status: %s", selectedDevice, sampleRate, ExtractStatus( status ) );
            InitFailed();
            return false;
        }
    }

    UInt32 frameSize;
    size = sizeof( UInt32 );
    status = AudioDeviceGetProperty( selectedDevice, 0, false, kAudioDevicePropertyBufferFrameSize, &size, &frameSize );
    if ( status != kAudioHardwareNoError )
    {
        common->Warning( "AudioDeviceGetProperty %d kAudioDevicePropertyBufferFrameSize failed.status: %s", selectedDevice, ExtractStatus( status ) );
        InitFailed();
        return false;
    }
    common->Printf( "current frame size: %d\n", frameSize );

    // get the allowed frame size range
    AudioValueRange frameSizeRange;
    size = sizeof( AudioValueRange );
    status = AudioDeviceGetProperty( selectedDevice, 0, false, kAudioDevicePropertyBufferFrameSizeRange, &size, &frameSizeRange );
    if ( status != kAudioHardwareNoError )
    {
        common->Warning( "AudioDeviceGetProperty %d kAudioDevicePropertyBufferFrameSizeRange failed. status: %s", selectedDevice, ExtractStatus( status ) );
        InitFailed();
        return false;
    }
    common->Printf( "frame size allowed range: %g %g\n", frameSizeRange.mMinimum, frameSizeRange.mMaximum );

    if ( frameSizeRange.mMaximum < MIXBUFFER_SAMPLES )
    {
        common->Warning( "can't obtain the required frame size of %d bits", MIXBUFFER_SAMPLES );
        InitFailed();
        return false;
    }

    if ( frameSize != (unsigned int)MIXBUFFER_SAMPLES )
    {
        frameSize = MIXBUFFER_SAMPLES;
        common->Printf( "setting frame size to: %d\n", frameSize );
        size = sizeof( frameSize );
        status = AudioDeviceSetProperty( selectedDevice, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, size, &frameSize );
        if ( status != kAudioHardwareNoError )
        {
            common->Warning( "AudioDeviceSetProperty %d kAudioDevicePropertyBufferFrameSize failed. status: %s", selectedDevice, ExtractStatus( status ) );
            InitFailed();
            return false;
        }
    }

    if ( idSoundSystemLocal::s_numberOfSpeakers.GetInteger() != 2 )
    {
        common->Warning( "only stereo sound currently supported" );
        idSoundSystemLocal::s_numberOfSpeakers.SetInteger( 2 );
    }
    UInt32 channels[ 2 ];
    size = 2 * sizeof( UInt32 );
    status = AudioDeviceGetProperty( selectedDevice, 0, false, 	kAudioDevicePropertyPreferredChannelsForStereo, &size, &channels );
    if ( status != kAudioHardwareNoError )
    {
        common->Warning( "AudioDeviceGetProperty %d kAudioDevicePropertyPreferredChannelsForStereo failed. status: %s", selectedDevice, ExtractStatus( status ) );
        InitFailed();
        return false;
    }
    common->Printf( "using stereo channel IDs %d %d\n", channels[ 0 ], channels[ 1 ] );

    status = AudioDeviceAddIOProc( selectedDevice, DeviceIOProc, NULL );
    if ( status != kAudioHardwareNoError )
    {
        common->Warning( "AudioDeviceAddIOProc failed. status: %s", ExtractStatus( status ) );
        InitFailed();
        return false;
    }
    activeIOProc = true;

    status = AudioDeviceStart( selectedDevice, DeviceIOProc );
    if ( status != kAudioHardwareNoError )
    {
        common->Warning( "AudioDeviceStart failed. status: %s", ExtractStatus( status ) );
        InitFailed();
        return false;
    }

    /*
    // allocate the mix buffer
    // it has the space for ROOM_SLICES_IN_BUFFER DeviceIOProc loops
    mixBufferSize =  dwSpeakers * dwSampleSize * dwPrimaryBitRate * ROOM_SLICES_IN_BUFFER / 8;
    mixBuffer = malloc( mixBufferSize );
    memset( mixBuffer, 0, mixBufferSize );
    */

    return true;
}