I am studying Microsoft XAudio2's X3Daudio sample code and have confused about sending the source voice parallel to both submix voice and mastering voice.
if( FAILED( hr = g_audioState.pXAudio2->CreateMasteringVoice( &g_audioState.pMasteringVoice ) ) )
{
SAFE_RELEASE( g_audioState.pXAudio2 );
return hr;
}
if( FAILED( hr = g_audioState.pXAudio2->CreateSubmixVoice( &g_audioState.pSubmixVoice, 1,
nSampleRate, 0, 0,
nullptr, &effectChain ) ) )
{
SAFE_RELEASE( g_audioState.pXAudio2 );
SAFE_RELEASE( g_audioState.pReverbEffect );
return hr;
}
//above second last argument nullptr->without sendlist pointer to submix voice, what I understand is, there is no output from this submix voice.
XAUDIO2_SEND_DESCRIPTOR sendDescriptors[2];
sendDescriptors[0].Flags = XAUDIO2_SEND_USEFILTER; // LPF direct-path
sendDescriptors[0].pOutputVoice = g_audioState.pMasteringVoice;
sendDescriptors[1].Flags = XAUDIO2_SEND_USEFILTER; // LPF reverb-path -- omit for better performance at the cost of less realistic occlusion
sendDescriptors[1].pOutputVoice = g_audioState.pSubmixVoice;
const XAUDIO2_VOICE_SENDS sendList = { 2, sendDescriptors };
// create the source voice
V_RETURN( g_audioState.pXAudio2->CreateSourceVoice( &g_audioState.pSourceVoice, pwfx, 0,
2.0f, nullptr, &sendList ) );
the source voice will send the sound to both mastering voice and submix voice. submix voice will ad reverb effect on the sound. But I don't see where submix voice send the post-processing and reverb effect enable sound to the mastering voice to output to the speaker.
If submix voice will default send its sound data to mastering voice if you do not specify the sendlist when you create it. Why in this sample, we also need send source voice to mastering voice at the same time? The demo output sound always with reverb effect on it. I don't see there is an option to disable the reverb effect in the sample executable.
I am so confused.
If you do not provide a send list, then a voice is automatically connected to the mastering voice. Per MSDN:
pSendList [in, optional]
Pointer to a list of XAUDIO2_VOICE_SENDS structures that describe
the set of destination voices for the submix voice. If pSendList is
NULL, the send list will default to a single output to the first
mastering voice created.
If you provide a send list, however, then the output of the voice does not go to the mastering voice unless you specify it in the sendlist. Hence why the source voice specifically sends to both the mastering voice and the submix voice.
The reason that reverb is done on the submix voice is an optimization. It allows all the reverb-affected source voices to do their processing including filtering and source-rate conversions into the submix voice, and then the often expensive effect (in this case the environment reverb) can run once instead of per-source-voice. Further, the submix voice is made to be mono instead of multi-channel so any stereo or multi-channel sources are down-mixed into the submix voice as well prior to the effect processing. Thirdly, this allows you to send some voices to the mastering voice and not the submix voice to be excluded from the reverb (typically HUD and interface sounds).
Note that the latest version of the XAudio2 samples can be found on GitHub. You might also want to take a look at DirectX Tool Kit for Audio.
Related
I am implementing a play through program from a (mono) microphone to a stereo output. For the output I configured a AudioStreamBasicDescription with two channels and set this ASBD to the input scope of the remote I/O unit.
However, when I configure the render callback to draw the system input no audio is played. On the other hand, when the ASBD is set to a single channel, audio is played without problems.
The audio unit render is implemented by:
AudioUnitRender(_rioUnit, ioActionFlags, inTimeStamp, 1, inNumberFrames, ioData)
Apparently, this is not sufficient to process and play the rendered input. Does anyone know how this should be done?
The number of channels in the ASBD for both sides of RemoteIO should be set the same, both mono, or both stereo. If you want stereo output, configure stereo input. Even if a monophonic mic is plugged-in (or internal).
I was trying to set up an audio unit to render the music (instead of Audio Queue.. which was too opaque for my purposes).. iOS doesn't have this property kAudioDevicePropertyBufferFrameSize.. any idea how I can derive this value to set up the buffer size of my IO unit?
I found this post interesting.. it asks about the possibility of using a combination of kAudioSessionProperty_CurrentHardwareIOBufferDuration and kAudioSessionProperty_CurrentHardwareOutputLatency audio session properties to determine that value.. but there is no answer.. any ideas?
You can use the kAudioSessionProperty_CurrentHardwareIOBufferDuration property, which represents the buffer size in seconds. Multiply this by the sample rate you get from kAudioSessionProperty_CurrentHardwareSampleRate to get the number of samples you should buffer.
The resulting buffer size should be a multiple of 2. I believe either 512 or 4096 are what you're likely to get, but you should always base it off of the values returned from AudioSessionGetProperty.
Example:
Float64 sampleRate;
UInt32 propSize = sizeof(Float64);
AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate,
&propSize,
&sampleRate);
Float32 bufferDuration;
propSize = sizeof(Float32);
AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration,
&propSize,
&bufferDuration);
UInt32 bufferLengthInFrames = sampleRate * bufferDuration;
The next step is to find out the input stream format of the unit you're sending audio to. Based on your description, I'm assuming that you're programmatically generating audio to send to the speakers. This code assumes unit is an AudioUnit you're sending audio to, whether that's the RemoteIO or something like an effect Audio Unit.
AudioStreamBasicDescription inputASBD;
UInt32 propSize = sizeof(AudioStreamBasicDescription);
AudioUnitGetProperty(unit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
0,
&inputASBD,
&propSize);
After this, inputASBD.mFormatFlags will be a bit field corresponding to the audio stream format that unit is expecting. The two most likely sets of flags are named kAudioFormatFlagsCanonical and kAudioFormatFlagsAudioUnitCanonical. These two have corresponding sample types AudioSampleType and AudioUnitSampleType that you can base your size calculation off of.
As an aside, AudioSampleType typically represents samples coming from the mic or destined for the speakers, whereas AudioUnitSampleType is usually for samples that are intended to be processed (by an audio unit, for example). At the moment on iOS, AudioSampleType is a SInt16 and AudioUnitSampleType is fixed 8.24 number stored in a SInt32 container. Here's a post on the Core Audio mailing list explaining this design choice
The reason I hold back from saying something like "just use Float32, it'll work" is because the actual bit representation of the stream is subject to change if Apple feels like it.
The audio unit itself decides on the actual buffer size, so the app's audio unit callback has to be able to handle any reasonable size given to it. You can suggest and poll the kAudioSessionProperty_CurrentHardwareIOBufferDuration property, but note that this value can while your app is running (especially during screen lock or call interruptions, etc.) outside of what the app can control.
I have been working with the MusicPlayer and MusicSequence classes to play MIDI files. However, I am wondering how to specify instruments for different channels. What is the MusicPlayer's default response to program change events? Can I tell the MusicPlayer to use certain samplers for certain channels? Or is the only way to set my own function as a MIDI Endpoint, and then handle the playing of notes myself using MusicDeviceMIDIEvent() to specify the sampler?
You can specify different instruments for different tracks in a MusicSequence. (MusicTrack API) I don't think MusicPlayer does anything with channels per se. You can specify that channels be converted to tracks when loading a MIDI file.
Music Sequence Load Flags
Flags used to configure the behavior of the MusicSequenceFileLoad and
MusicSequenceFileLoadData functions.
enum { kMusicSequenceLoadSMF_ChannelsToTracks = (1 << 0) }; typedef
UInt32 MusicSequenceLoadFlags;
Constants
kMusicSequenceLoadSMF_ChannelsToTracks
If this flag is set the resultant Sequence will contain a tempo track, 1 track for each MIDI Channel that is found in the SMF, 1 track
for SysEx or MetaEvents - and this will be the last track in the
sequence after the LoadSMFWithFlags calls.
Available in OS X v10.3 and later.
Declared in MusicPlayer.h.
I am trying to develop a player using AVFoundation and enable fast forward and rewind. I am setting the player's rate property to 0, 0.25, 0.5, 1, 1.5, 2.0.
rate property of 0,1 is working as expected and setting it to pause and play.
0.25, 0.5 also works and displays video in slow motion.
My question is that setting the property of 1.5, 2.0 is not working, it just keeps playing. This works for .mp4 videos though. Is this not supported for HLS? I am using the sample HLS stream's provided by Apple.
http://devimages.apple.com/iphone/samples/bipbopgear4.html
How do we do enable rewind and fast forward? Should I somehow use seekToTime?
Any help will be appreciated !
Looks like if I have an i-Frame playlist, FF/RW is supported. But then thats only from iOS5.0+.
Confirmed from Apple Dev Forums.
Rate is supported only for I-Frame Playlists for HLS content. For normal playlist, only rate = 0, 1 is supported(which is essentially play/pause)
For non-HLS content, rate can be use for <0, =0,>0 to support FF/RW/Slow forward etc.
The rate property only controls playback speed. 0 for stopped and up to 1 for the normal rate of the current item. Any value over 1 is treated as 1. If you want to "fast forward" to a specific point you will need to use the method you mentioned, "seekToTime". There is no way (AFAIK) to play a movie faster than it's normal rate using public API's. Hope that helps.
Is there an API in one of the iOS layers that I can use to generate a tone by just specifying its Hertz. What I´m looking to do is generate a DTMF tone. This link explains how DTMF tones consists of 2 tones:
http://en.wikipedia.org/wiki/Telephone_keypad
Which basically means that I should need playback of 2 tones at the same time...
So, does something like this exist:
SomeCleverPlayerAPI(697, 1336);
If spent the whole morning searching for this, and have found a number of ways to playback a sound file, but nothing on how to generate a specific tone. Does anyone know, please...
Check out the AU (AudioUnit) API. It's pretty low-level, but it can do what you want. A good intro (that probably already gives you what you need) can be found here:
http://cocoawithlove.com/2010/10/ios-tone-generator-introduction-to.html
There is no iOS API to do this audio synthesis for you.
But you can use the Audio Queue or Audio Unit RemoteIO APIs to play raw audio samples, generate an array of samples of 2 sine waves summed (say 44100 samples for 1 seconds worth), and then copy the results in the audio callback (1024 samples, or whatever the callback requests, at a time).
See Apple's aurioTouch and SpeakHere sample apps for how to use these audio APIs.
The samples can be generated by something as simple as:
sample[i] = (short int)(v1*sinf(2.0*pi*i*f1/sr) + v2*sinf(2.0*pi*i*f2/sr));
where sr is the sample rate, f1 and f1 are the 2 frequencies, and v1 + v2 sum to less than 32767.0. You can add rounding or noise dithering to this for cleaner results.
Beware of clicking if your generated waveforms don't taper to zero at the ends.