Esempio n. 1
0
OSStatus AudioOutputVolumeDown(AudioDeviceID device, UInt32 *level) {
  Float32 right, left;
  OSStatus err = AudioOutputGetVolume(device, &left, &right);
  if (noErr == err) {
    Float32 max = left > right ? left : right;
    UInt32 lvl = __AudioOutputVolumeGetLevel(max);
    if (0 == lvl) {
      /* If not min level */
      if (fnonzero(max)) {
        err = _AudioOutputSetVolume(device, left, right, 0);
      }
    } else {
      lvl--;
      check(lvl <= kAudioOutputVolumeMaxLevel);
      err = _AudioOutputSetVolume(device, left, right, kAudioOutputVolumeLevels[lvl]);
    }
    if (level) *level = lvl;
  }
  return err;
}
bool	operator<(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y)
{
	bool theAnswer = false;
	bool isDone = false;
	
	//	note that if either side is 0, that field is skipped
	
	//	format ID is the first order sort
	if((!isDone) && ((x.mFormatID != 0) && (y.mFormatID != 0)))
	{
		if(x.mFormatID != y.mFormatID)
		{
			//	formats are sorted numerically except that linear
			//	PCM is always first
			if(x.mFormatID == kAudioFormatLinearPCM)
			{
				theAnswer = true;
			}
			else if(y.mFormatID == kAudioFormatLinearPCM)
			{
				theAnswer = false;
			}
			else
			{
				theAnswer = x.mFormatID < y.mFormatID;
			}
			isDone = true;
		}
	}
	
	
	//  mixable is always better than non-mixable for linear PCM and should be the second order sort item
	if((!isDone) && ((x.mFormatID == kAudioFormatLinearPCM) && (y.mFormatID == kAudioFormatLinearPCM)))
	{
		if(((x.mFormatFlags & kIsNonMixableFlag) == 0) && ((y.mFormatFlags & kIsNonMixableFlag) != 0))
		{
			theAnswer = true;
			isDone = true;
		}
		else if(((x.mFormatFlags & kIsNonMixableFlag) != 0) && ((y.mFormatFlags & kIsNonMixableFlag) == 0))
		{
			theAnswer = false;
			isDone = true;
		}
	}
	
	//	floating point vs integer for linear PCM only
	if((!isDone) && ((x.mFormatID == kAudioFormatLinearPCM) && (y.mFormatID == kAudioFormatLinearPCM)))
	{
		if((x.mFormatFlags & kAudioFormatFlagIsFloat) != (y.mFormatFlags & kAudioFormatFlagIsFloat))
		{
			//	floating point is better than integer
			theAnswer = y.mFormatFlags & kAudioFormatFlagIsFloat;
			isDone = true;
		}
	}
	
	//	bit depth
	if((!isDone) && ((x.mBitsPerChannel != 0) && (y.mBitsPerChannel != 0)))
	{
		if(x.mBitsPerChannel != y.mBitsPerChannel)
		{
			//	deeper bit depths are higher quality
			theAnswer = x.mBitsPerChannel < y.mBitsPerChannel;
			isDone = true;
		}
	}
	
	//	sample rate
	if((!isDone) && fnonzero(x.mSampleRate) && fnonzero(y.mSampleRate))
	{
		if(fnotequal(x.mSampleRate, y.mSampleRate))
		{
			//	higher sample rates are higher quality
			theAnswer = x.mSampleRate < y.mSampleRate;
			isDone = true;
		}
	}
	
	//	number of channels
	if((!isDone) && ((x.mChannelsPerFrame != 0) && (y.mChannelsPerFrame != 0)))
	{
		if(x.mChannelsPerFrame != y.mChannelsPerFrame)
		{
			//	more channels is higher quality
			theAnswer = x.mChannelsPerFrame < y.mChannelsPerFrame;
			isDone = true;
		}
	}
	
	return theAnswer;
}
const AudioTimeStamp &	AUTimestampGenerator::GenerateInputTime(Float64 framesToAdvance, double inputSampleRate)
{
	if (mBypassed)
		return mCurrentOutputTime;

	double inputSampleTime;
	
	mCurrentInputTime.mFlags = kAudioTimeStampSampleTimeValid;
	double rateScalar = 1.0;
	
	// propagate rate scalar
	if (mCurrentOutputTime.mFlags & kAudioTimeStampRateScalarValid) {
		mCurrentInputTime.mFlags |= kAudioTimeStampRateScalarValid;
		mCurrentInputTime.mRateScalar = rateScalar = mCurrentOutputTime.mRateScalar;
	}
	
	// propagate host time and sample time
	if (mCurrentOutputTime.mFlags & kAudioTimeStampHostTimeValid) {
		mCurrentInputTime.mFlags |= kAudioTimeStampHostTimeValid;
		mCurrentInputTime.mHostTime = mCurrentOutputTime.mHostTime;
		if (mHostTimeDiscontinuityCorrection && mDiscontinuous && (mLastOutputTime.mFlags & kAudioTimeStampHostTimeValid)) {
			// we had a discontinuous output time, need to resync by interpolating 
			// a sample time that is appropriate to the host time
			UInt64 deltaHostTime = mCurrentOutputTime.mHostTime - mLastOutputTime.mHostTime;
			double deltaSeconds = double(deltaHostTime) * CAHostTimeBase::GetInverseFrequency();
			// samples/second * seconds = samples
			double deltaSamples = floor(inputSampleRate / rateScalar * deltaSeconds + 0.5);
			double lastInputSampleTime = mCurrentInputTime.mSampleTime;
			inputSampleTime = lastInputSampleTime + deltaSamples;
#if DEBUG
			if (mVerbosity > 1)
				printf("%-20.20s: adjusted input time: "TSGFMT" -> "TSGFMT" (SR=%.3f, rs=%.3f)\n", mDebugName, (SInt64)lastInputSampleTime, (SInt64)inputSampleTime, inputSampleRate, rateScalar);
#endif
			mDiscontinuous = false;
		} else {
			inputSampleTime = mNextInputSampleTime;
		}
	} else {
		// we don't know the host time, so we can't do much
		inputSampleTime = mNextInputSampleTime;
	}

	if (!mHostTimeDiscontinuityCorrection && fnonzero(mDiscontinuityDeltaSamples))
	{
		// we had a discontinuous output time, need to resync by propagating the
		// detected discontinuity, taking the rate scalar adjustment into account
		inputSampleTime += floor(mDiscontinuityDeltaSamples / mRateScalarAdj + 0.5);
		
#if DEBUG
		if (mVerbosity > 1)
			printf("%-20.20s: adjusted input time: %.0f -> %.0f (SR=%.3f, rs=%.3f, delta=%.0f)\n", mDebugName, mNextInputSampleTime, inputSampleTime, inputSampleRate, mRateScalarAdj, mDiscontinuityDeltaSamples);
#endif
		
		mDiscontinuityDeltaSamples = 0.;
	}
	
	
	// propagate word clock
	if (mCurrentOutputTime.mFlags & kAudioTimeStampWordClockTimeValid) {
		mCurrentInputTime.mFlags |= kAudioTimeStampWordClockTimeValid;
		mCurrentInputTime.mWordClockTime = mCurrentOutputTime.mWordClockTime;
	}
	
	// propagate SMPTE time
	if (mCurrentOutputTime.mFlags & kAudioTimeStampSMPTETimeValid) {
		mCurrentInputTime.mFlags |= kAudioTimeStampSMPTETimeValid;
		mCurrentInputTime.mSMPTETime = mCurrentOutputTime.mSMPTETime;
	}
	
	// store the input sample time and expected next input time
	mCurrentInputTime.mSampleTime = inputSampleTime;
	mNextInputSampleTime = inputSampleTime + framesToAdvance;

#if DEBUG
	if (mVerbosity > 0) {
		printf("%-20.20s: out = "TSGFMT" (%10.3fs)  in = "TSGFMT"  (%10.3fs)  delta = "TSGFMT"  advance = "TSGFMT"\n", mDebugName, (SInt64)mCurrentOutputTime.mSampleTime, DebugHostTime(mCurrentOutputTime), (SInt64)inputSampleTime, DebugHostTime(mCurrentInputTime), (SInt64)(mCurrentOutputTime.mSampleTime - inputSampleTime), (SInt64)framesToAdvance);
	}
#endif
	return mCurrentInputTime;
}