Audiorecorder, Choosing the input channels. Mac and RME - macos

I am trying to simply record sound through an external sound card: RME Fireface 400.
This is the code I am using:
AO = audioplayer(mls_o,fs,16,5); % mls_o is the signal that is played.
AI = audiorecorder(fs,16,2,5); % 2 CHANNELS BUT HOW DO I ASSIGN THEM
play(AO);%playing
recordblocking(AI,1,2);%recording
y_rec=getaudiodata(AI);
delete(AI);% Deleting the objects
delete(AO);
I can only chose the number of channels, but not to address them.
Audiorecorder only supports 2 channels and Fireface have 8 input channels. I have to use the first two analog: ch5 and ch6. However, by default audio recorder only look 1st and 2nd one, which are mic inputs.
Otherwise do you know any other way of doing that?

I don't think you can do this with just the audiorecorder object. Check out the playrec library and pa-wavplay FileExchange submission, either of which should be capable of doing what you need. I believe Psychtoolbox also allows you to do this, but that might be overkill for your needs.

Related

How to properly use MIDIReadProc?

According to apple's docs it says:
Because your MIDIReadProc callback is invoked from a separate thread,
be aware of the synchronization issues when using data provided by
this callback.
Does this mean, use #synchronize to do thread blocking for safety?
Or does this literally mean synchronization timing issues may happen?
I am currently trying to read a midi file, and use a MIDIReadProc to trigger the note-on / note-off of a software synth based off of midi events. I need this to be extremely reliable and perfectly in-time. Right now, I am noticing that when I consume these midi events and write the audio to a buffer (all done from the MIDIReadProc), the timing is extremely sloppy and not sounding right at all. So I would like to know, what is the "proper" way to consume midi events from a MIDIReadProc?
Also, is a MIDIReadProc the only option for consuming midi events from a midi file?
Is there another option as far as setting up a virtual endpoint that could be directly consumed by my synthesizer? If so, how does that work exactly?
If you presume a function of this format to be the midiReadProc,
void midiReadProc(const MIDIPacketList *packetList,
void* readProcRefCon,
void* srcConnRefCon)
{
MIDIPacket *packet = (MIDIPacket*)packetList->packet;
int count = packetList->numPackets;
for (int k=0; k<count; k++) {
Byte midiStatus = packet->data[0];
Byte midiChannel= midiStatus & 0x0F;
Byte midiCommand = midiStatus >> 4;
//parse MIDI messages, extract relevant information and pass it to the controller
//controller must be visible from the midiReadProc
}
packet = MIDIPacketNext(packet);
}
the MIDI client has to be declared in the controller, interpreted MIDI events get stored into the controller from MIDI callback and read by the audioRenderCallback() on each audio render cycle. This way you can minimize timing imprecisions to the
length of the audio buffer, which you can negotiate during AudioUnit setup to be as short as the system allows for.
A controller can be a #interface myMidiSynthController : NSViewController you define, consisting of a matrix of MIDI channels and a pre-determined maximum-polyphony-per-channel, among other relevant data such as interface elements, phase accumulators for each active voice, AudioComponentInstance, etc... It would be wrong to resize the controller based on the midiReadProc() input. RAM is cheap nowadays.
I'm using such MIDI callbacks for processing live input from MIDI devices. Concerning playback of MIDI files, if you
want to process streams or files of arbitrary complexity, you may also run into surprises. MIDI standard itself
has timing features, which work as good as MIDI hardware allows for. Once you read an entire file into the memory, you can
translate your data into whatever you want and use your own code for controlling sound synthesis.
Please, observe not to use any code which would block the audio render thread (i.e. inside audioRenderCallback()), or would do memory management on it.
You could use AVAudioEngine.musicSequence and prepare your audio unit graph. Then use the MusicSequence API to load your GM file. Like this you don’t need to do the timing by yourself. Note I have not done this myself so far but I understand in theory it should work like this.
After you instantiate your synthesizer audio unit, you attach and connect it to the AVAudioEngine graph.
Does this mean, use #synchronize to do thread blocking for safety?
The opposite of what you’ve said is true: You should certainly not lock in a realtime thread. The #synchronized directive will lock if the resource is already locked. You may consider to use lock-free queues for realtime threads. See also Four common mistakes in audio development.
If you have to use CoreMIDI and MIDIReadProc, you can send MIDI commands to the synthesizer audio unit by calling MusicDeviceMIDIEvent right from your callback.

How to reduce Audio Latency by MATLAB DSP System Toolbox?

I have been working on my ANC project. For this I have two microphone inputs and one loud speaker output, but initially I am using single microphone and dspStreamingPassthrough to pass microphone input to loud speaker. Here is my code
% Initialization
numIterations = 500;
% Construct sources (for all inputs)
src1 = dsp.AudioRecorder('DeviceName','Mikrofon (USB-Audiogerät)','NumChannels',1);
% Construct sinks (for all outputs)
sink1_1 = dsp.SpectrumAnalyzer('SampleRate',44100, ...
'PlotAsTwoSidedSpectrum',false, ...
'ShowLegend',true);
sink1_2 = dsp.TimeScope('BufferLength',44100, ...
'SampleRate',44100, ...
'TimeSpan',1, ...
'ShowLegend',true, ...
'ShowGrid',true, ...
'YLimits',[-0.5 0.5]);
sink1_3 =
dsp.AudioPlayer('BufferSizeSource','Property','BufferSize',1024,...
'QueueDuration',0,'OutputNumUnderrunSamples',true);
sink1_3.DeviceName = 'Lautsprecher (USB-Audiogerät)';
% Stream processing loop
clear dspStreamingPassthrough;
for i = 1:numIterations
% Sources
in1 = step(src1);
% User Algorithm
out1 = dspStreamingPassthrough(in1);
% Sinks
step(sink1_3,out1);
step(sink1_1,out1);
step(sink1_2,out1);
nUnderrun=step(sink1_3,out1);
end
% Clean up
release(src1);
release(sink1_1);
release(sink1_2);
I am using Windows DirectSound Audio driver ( I cannot use ASIO driver as I cannot access individual audio devices names. ! ) Now I have the audio latency of 1.2 seconds i.e if I say ''hello'' in microphone now, after 1.2 seconds speaker is saying ''hello''(this is absolutely with out any audio input data processing just 'dspStreamingPassthrough'). How to reduce this incredible delay ?
For my project of 1 meter length pipe(air duct), I should be able to process the data in 1.7 msec or less !! I have tried with lowest 'BufferSize' and lowest 'QueueDuration' possible !!
What other parameters can influence to speed up this process? Is it possible with MATLAB or not ?
PS: -sorry for whole code. -I am using a cheap quality Sound card (7 euros)
DirectSound has way higher latency than ASIO because DirectSound is not suited for low-latency apps. DSP System Toolbox does not support WASAPI yet.
The latency performance of these objects was greatly improved starting in 15a. I am not sure which version you are running but try and upgrade to 15a or higher.
As for tuning your latency, try the following:
* Set the Queue Duration property to 0 seconds for both player and recorder.
* For the recorder, match the SamplesPerFrame and BufferSize property.
* For the player, ensure that the size of the data matches the BuferSize property.
The BufferSize property is the size at which the sound card operates.
If you get drops, increase the BufferSize value. There can be many reasons for the drops:
* The algorithm you are running is not faster than BufferSize/SampleRate
* The soundcard is not able to operate at this BufferSize. Some sound-cards allow you to modify this when using ASIO.
* Limitation of the player/recorder objects.
Hope this helps.
Dinesh

How to use audioConverterFillComplexBuffer and its callback?

I need a step by step walkthrough on how to use audioConverterFillComplexBuffer and its callback. No, don't tell me to read the Apple docs. I do everything they say and the conversion always fails. No, don't tell me to go look for examples of audioConverterFillComplexBuffer and its callback in use - I've duplicated about a dozen such examples both line for line and modified and the conversion always fails. No, there isn't any problem with the input data. No, it isn't an endian issue. No, the problem isn't my version of OS X.
The problem is that I don't understand how audioConverterFillComplexBuffer works, so I don't know what I'm doing wrong. And nothing out there is helping me understand, because it seems like nobody on Earth really understands how audioConverterFillComplexBuffer works, either. From the people who actually use it(I spy cargo cult programming in their code) to even the authors of Learning Core Audio and/or Apple itself(http://stackoverflow.com/questions/13604612/core-audio-how-can-one-packet-one-byte-when-clearly-one-packet-4-bytes).
This isn't just a problem for me, it's a problem for anybody who wants to program high-performance audio on the Mac platform. Threadbare documentation that's apparently wrong and examples that don't work are no fun.
Once again, to be clear: I NEED A STEP BY STEP WALKTHROUGH ON HOW TO USE audioConverterFillComplexBuffer plus its callback and so does the entire Mac developer community.
This is a very old question but I think is still relevant. I've spent a few days fighting this and have finally achieved a successful conversion. I'm certainly no expert but I'll outline my understanding of how it works. Note I'm using Swift, which I'm also just learning.
Here are the main function arguments:
inAudioConverter: AudioConverterRef: This one is simple enough, just pass in a previously created AudioConverterRef.
inInputDataProc: AudioConverterComplexInputDataProc: The very complex callback. We'll come back to this.
inInputDataProcUserData, UnsafeMutableRawPointer?: This is a reference to whatever data you may need to be provided to the callback function. Important because even in swift the callback can't inherit context. E.g. you may need to access an AudioFileID or keep track of the number of packets read so far.
ioOutputDataPacketSize: UnsafeMutablePointer<UInt32>: This one is a little misleading. The name implies it's the packet size but reading the documentation we learn it's the total number of packets expected for the output format. You can calculate this as outPacketCount = frameCount / outStreamDescription.mFramesPerPacket.
outOutputData: UnsafeMutablePointer<AudioBufferList>: This is an audio buffer list which you need to have already initialized with enough space to hold the expected output data. The size can be calculated as byteSize = outPacketCount * outMaxPacketSize.
outPacketDescription: UnsafeMutablePointer<AudioStreamPacketDescription>?: This is optional. If you need packet descriptions, pass in a block of memory the size of outPacketCount * sizeof(AudioStreamPacketDescription).
As the converter runs it will repeatedly call the callback function to request more data to convert. The main job of the callback is simply to read the requested number packets from the source data. The converter will then convert the packets to the output format and fill the output buffer. Here are the arguments for the callback:
inAudioConverter: AudioConverterRef: The audio converter again. You probably won't need to use this.
ioNumberDataPackets: UnsafeMutablePointer<UInt32>: The number of packets to read. After reading, you must set this to the number of packets actually read (which may be less than the number requested if we reached the end).
ioData: UnsafeMutablePointer<AudioBufferList>: An AudioBufferList which is already configured except for the actual data. You need to initialise ioData.mBuffers.mData with enough capacity to hold the expected number of packets, i.e. ioNumberDataPackets * inMaxPacketSize. Set the value of ioData.mBuffers.mDataByteSize to match.
outDataPacketDescription: UnsafeMutablePointer<UnsafeMutablePointer<AudioStreamPacketDescription>?>?: Depending on the formats used, the converter may need to keep track of packet descriptions. You need to initialise this with enough capacity to hold the expected number of packet descriptions.
inUserData: UnsafeMutableRawPointer?: The user data that you provided to the converter.
So, to start you need to:
Have sufficient information about your input and output data, namely the number of frames and maximum packet sizes.
Initialise an AudioBufferList with sufficient capacity to hold the output data.
Call AudioConverterFillComplexBuffer.
And on each run of the callback you need to:
Initialise ioData with sufficient capacity to store ioNumberDataPackets of source data.
Initialise outDataPacketDescription with sufficient capacity to store ioNumberDataPackets of AudioStreamPacketDescriptions.
Fill the buffer with source packets.
Write the packet descriptions.
Set ioNumberDataPackets to the number of packets actually read.
return noErr if successful.
Here's an example where I read the data from an AudioFileID:
var converter: AudioConverterRef?
// User data holds an AudioFileID, input max packet size, and a count of packets read
var uData = (fRef, maxPacketSize, UnsafeMutablePointer<Int64>.allocate(capacity: 1))
err = AudioConverterNew(&inStreamDesc, &outStreamDesc, &converter)
err = AudioConverterFillComplexBuffer(converter!, { _, ioNumberDataPackets, ioData, outDataPacketDescription, inUserData in
let uData = inUserData!.load(as: (AudioFileID, UInt32, UnsafeMutablePointer<Int64>).self)
ioData.pointee.mBuffers.mDataByteSize = uData.1
ioData.pointee.mBuffers.mData = UnsafeMutableRawPointer.allocate(byteCount: Int(uData.1), alignment: 1)
outDataPacketDescription?.pointee = UnsafeMutablePointer<AudioStreamPacketDescription>.allocate(capacity: Int(ioNumberDataPackets.pointee))
let err = AudioFileReadPacketData(uData.0, false, &ioData.pointee.mBuffers.mDataByteSize, outDataPacketDescription?.pointee, uData.2.pointee, ioNumberDataPackets, ioData.pointee.mBuffers.mData)
uData.2.pointee += Int64(ioNumberDataPackets.pointee)
return err
}, &uData, &numPackets, &bufferList, nil)
Again, I'm no expert, this is just what I've learned by trial and error.

Detecting if the microphone is on

Is there a way to programmatically detect whether the microphone is on on Windows?
No, microphones don't tell you whether they're ‘on’ or that a particular sound channel is connected to a microphone device. The best you can do is to read audio data from the input channel you suspect to be a microphone (eg. the Windows default input device/channel), and see if there's any signal on it.
To do that you'd have to remove any DC offset and look for any signal above a reasonable noise floor. (Be generous: many cheap audio input devices are quite noisy even when there is no signal coming in. A mid-band filter/FFT would also be useful to detect only signals in the mid-range of a voice and not low-frequency hum and transient clicks.)
This is not tested in any way, but I would try to read some samples and see if there is any variation. If the mike is on then you should get different values from the ambient sounds. If the mike is off you should get a 0. Again this is just how I imagine things should work - I don't know if they actually work that way.
Due to a happy accident, I may have discovered that yes there is a way to detect the presence of a connected microphone.
If your windows "recording devices" shows "no microphone", then this approach (using the Microsoft Speech API) will work and confirm you have no mic. If windows however thinks you have a mic, this won't disagree.
#include <sapi.h>
#include <sapiddk.h>
#include <sphelper.h>
CComPtr<ISpRecognizer> m_cpEngine;
m_cpEngine.CoCreateInstance(CLSID_SpInprocRecognizer);
CComPtr<ISpObjectToken> pAudioToken;
HRESULT hr = SpGetDefaultTokenFromCategoryId(SPCAT_AUDIOIN, &pAudioToken);
if (FAILED(hr)) ::OutputDebugString("no input, aka microphone, detected");
more specifically, hr will return this result:
SPERR_NOT_FOUND 0x8004503a -2147200966
The requested data item (data key, value, etc.) was not found.

audio power on AudioQueue

I'm now creating an Application using speech recognition.To check the Audio Power coming in through the microphone,
I wrote a method as follows.
-(void)checkPower(AudioqueRef)queue{
UInt32 expectedSize= sizeof(AudioQueueLevelMeterState);
AudioQueueGetProperty(queue,
kAudioQueueProperty_CurrentLevelMeter,
audioLevels,
expectedSize);
NSLog(#"average:%f peak:%f",audioLevels.mAveragePower,audioLevels.mPeakPower);
}
I found that sometimes mAveragePower was larger than mPeakPower,
and when mAveragePower was 1.0, in other words, averagePower
is regarded as max, mPeakPower was lower than 1.0.
I think that generally this result is inpossible.
please Let me know if you have any information about sound power on CoreAudio.
thanks.
I think mPeakPower means channel power at CURRENT moment & mAveragePower - average channel power for ALL record time, and if it's right your result possible.

Resources