Setting an AudioUnit's SampleRate to 16000 Hz without using an AudioSession - iphone

I would like to request a 16k Hz sample rate without using an audio session, but have thus far not been successful.
Querying the hardware via AudioUnitGetProperty / SampleRate before configuring the mic / speakers reveals an mSampleRate of 0, which is described in the documentation as implying that any sample rate is supported, but it is also stated that the hardware will actually give you the nearest one that it supports. After I request 16k and query the hardware again the mSampleRate is 44100 for both mic and speakers respectively. Querying the input/output scope of the input/output busses using AudioUnitGetProperty / SampleRate returns 0 in all cases, as does using the equivalent query with StreamFormat instead. Querying with AudioSessionGetProperty / CurrentHardwareSampleRate, despite the session not being configured or initialized, returns 44100. Everything works as expected when using an audio session, but this is not described as necessary in the documentation, except for submitting to the app store which I am not doing.
It is also not clear to me whether, when using an audio session and requesting 16k Hz, the session quietly converts to 16k between the input and output scopes of the input bus, or whether the hardware does actually support "any" sample rate as mentioned in the documentation. It would also be nice to have a list of sample rates supported by the hardware - it's hard to understand why there isn't a queryable list.
I'm interested in any relevant documentation that describes how to do this (without a session), or explains exactly which sample rates I can set the output scope of the input bus to. I have seen discussion in various threads here that it must be a downshift of 44.1k, but I have thus far not found any documentation supporting that assertion.
Many thanks.

Related

Must the "telephone-event" have the same frequency as the codec used in the call?

I use RFC2833 as the DTMF transmitting method for the calls.
Q1: Must the "telephone-event" have the same frequency as the codec used in the call?
E.g. If I use SPEEX 16000 then can I have telephone-event/8000?
Q2: And can I have SDP without any audio codecs but, with specified "telephone-event"?
E. g. can I have an SDP like that:
m=audio 12346 RTP/AVP 100
a=rtpmap:100 telephone-event/8000
a=fmtp:100 0-15,66,70
Q1: Yes. Here is the proof, taken from RFC errata:
Named telephone events are carried as part of the audio stream and if
they use the same SSRC (therefore the same timing and sequence number
space), they MUST use the same timestamp clock rate as the regular
audio channel.
Q2: Most probably, yes. But, still, I'm not very sure.
Interesting question, I am wondering what usage you have in mind.
First some standard related piece of information:
rfc4733 is applicable here. rfc4733 has obsoleted rfc2833.
In rfc4733, play-out in audio stream of telephone-events is described, it is recommended to use the same rate of the audio stream.
So Q1 answer is positive, in theory you can have mixed rates. It means you do not follow the recommendation, you are on your own! In practice, only equipment supporting multiple rates would accept it.
Q2 is not really clear I guess. If it is a special case of Q1 with no audio stream, I doubt that use-case is supported at all. After all, both share the same RTP SSRC field.

Can I send sound buffers received using AVAudioSinkNode to be rendered in real-time using AVAudioSourceNode?

I am experimenting with the new AVAudioSinkNode and AVAudioSourceNode nodes, for use with AVAudioEngine.
In terms of setup, similar to the tests described in this other post, my sink node is attached to the input node (e.g. microphone) and my source node is attached to the output node (e.g. speaker). The sink callback is working as expected. Separately, on the source node's side I generated a sine wave signal--the source node also appears to be working properly.
Question
For testing purposes, I'd like to send the (float) buffers captured at the sink node to the source node, preferably in real time and without saving to a file. This should have the effect of replaying the microphone input to the speaker output. Is there a (simple?) way to do this?
Essentially I'm looking for a way to connect the sink node to the source node even though the nodes might not be meant to be used this way, given that the sink node has no output bus and the source node has no input bus (Source).
I assume I could connect the input node to a mixer connected to the output node in order to channel microphone input to the speaker, but for my purposes I would like to use the new sink and source nodes in the configuration as described.
I was thinking I would need to queue up the buffers captured by my sink node in some way until they can be read by the source node to fill its own buffers. I looked into Audio Queue Services but it doesn't seem appropriate.
The way to do this in real time is to use Audio Unit callbacks (the buffers of which can be as small as a few milliseconds). They will almost always be the same size (except maybe at device power state changes), so just save each one, process it as needed, and have it ready for the next output, a few mS later. Or use a circular/ring fifo/buffer. The RemoteIO Audio Unit in iOS has synchronized I/O.

How to handle duplicate note_on, note_off, tempo change in more than one tracks, and tracks without program_change in a midi file?

I'm using Mido for python, working on parsing midi files into <start_time, duration, program, pitch> tuples and met some problems.
Some files that I parse has multiple note_on, resulting in notes at the same pitch and same program being opened more than once.
Some files contains multiple note_off resulting in trying to close notes that is no longer on due to being closed before (assuming only one note at the same program and same pitch can be on).
Some tracks does not have a program_change in the beginning of the track (or even worse, not even having one in the whole track).
Some files has more than one track containing set_tempo messages.
What should I do in each of these cases to ensure I get the correct interpretation?
In general, to get a correct MIDI message stream, you have to merge all tracks in a type 1 file. What matters for a synthesizer are not tracks, but channels.
The MIDI specification says:
ASSIGNMENT OF NOTE ON/OFF COMMANDS
If an instrument receives two or more Note On messages with the same key number and MIDI channel, it must make a determination of how to handle the additional Note Ons. It is up to the receiver as to whether the same voice or another voice will be sounded, or if the messages will be ignored. The transmitter, however, must send a corresponding Note Off message for every Note On sent. If the transmitter were to send only one Note Off message, and if the receiver in fact assigned the two Note On messages to different voices, then one note would linger. Since there is no harm or negative side effect in sending redundant Note Off messages this is the recommended practice.
The General MIDI System Level 1 Developer Guidelines say that in response to a “GM System On” message, a device should set Program Change to 0. So you can assume this to be the initial value for channels that have notes without a preceding Program Change.
The Standard MIDI Files specification says that
tempo information should always be stored in the first MTrk chunk.
But "should" is not "must".

STM32F302 Adc with DMA for different size and channel

I'm using STM32F302 QFN32 and unfortunately, it has only one ADC module. One channel must get around 500 samples in one period and it must be sync with and PWM (thinking using a timer and this i/o will be toggled in callback, because while reading its ADC channel, I must know the i/o whether high or low, so that according to this value, will decide value). Furthermore, there are 4 more channels which must be read.(More samples doesn't need there like before, 8 or 16 samples will be enough.) However, it has only one ADC module. Consequently, Can I do this? If yes, how? Thank you.
ST ADC have two conversion modes. Regular and Injected.
Regular mode is like all ADC's have. You start it, either by software or trigger (timer/gpio) and it does one or a sequence of conversions. The result is written to a common register, that the DMA takes care of.
Injected mode is a high priority preemption conversion. Once you start an injected conversion sequence by software or trigger. The ADC injects the conversion between the regular conversions. As a higher priority one. The result is stored in one of the injected result channel for the interrupt.
Only regular mode supports DMA. See AN4195 for more info.
I suggest you use a timer to trigger a regular sequence for your fast channel, with a circular DMA setup to move the data. And use another timer to trigger the injected sequence. There is a maximum of 4 injected channels, so you are in luck!
Obviously, you can do this the other way around. Have fast injections and slow regular. But you'll need another timer synchronized to the injected start trigger to get the DMA to move the data.
That is, if your samplerate does not allow immediate processing. Otherwise you can just use the ISR.

AHCI Driver for own OS

I have been programming a little AHCI driver for two weeks. I have read this article and Intel's Serial ATA Advanced Host Controller Interface (AHCI) 1.3. There is an example, which shows how to read sectors via DMA mode (osdev.org). I have done this operation (ATA_CMD_READ_DMA 0xC8) successfully, but when i tried to write sectors (ATA_CMD_WRITE_DMA 0xCA) to the device, the HBA set the error
Offset 30h: PxSERR – Port x Serial ATA Error - Handshake Error
(this is decoding from Intel AHCI specification). I don't understand why it happened. Please, help me.
In addition, I have tried to issue the command IDENTIFY 0xEC, but not successfully...
You asked this question nearly two months ago so I'm not sure if you've already figured this out. Please note that I'm writing from memory in terms of what must be done first, etc. I may not have remembered all, or accurately, what must be done. You should reference the AHCI spec for everything. The methods for doing this are as varied as there are programmers that have done this. For this reason, I'm not including code examples.
For starters, ensure that you've set the HBA state machine accordingly. You'll be able to find references for the state machines supported by the HBA in that same SATA spec 1.3. In lieu of this, you should check a few registers.
Please note that all page numbers are given with respect to viewing in Adobe Acrobat and are 8 pages more than numbered in the actual document
From page 24 and 25 of the spec., check GHC.IE and GHC.AE. These two will turn on interrupts and ensure that the HBA is working in AHCI mode. Another, very important register to check, is CAP.SSS (Page 23). If this bit is high, then the HBA Supports Staggered Spin-up. This means that the HBA will not perform any protocol negotiation for any port. Before you do the following, store the value of PxSIG (Page 35 and 36).
To actually spin up the port, you'll need to visit pages 33, 34 and 35 of the spec. These pages cover the PxCMD register. For each port supported by the HBA (check CAP.NP to know how many are there), you'll have to switch high bit PxCMD.SUD. After switching that bit high, you'll want to poll on PxSSTS (Page 36) to check the state of the PHY. You can check CAP.ISS in order to know what speed you can expect to see "come alive" on PxSSTS.
After spinning up the port, check PxSIG (Page 35 & 36). The value should be different than when you started. I don't recall now what you can expect them to become, but they will be different. When communication is actually established, the device sends to the host an initial FIS. Without this first FIS, the HBA will be unable to communicate with the device. (It's with this first FIS that the HBA sets the correct bits in PxSIG.)
Finally, after all of this, you'll need to set PxCMD.FRE (page 34). This bit in the port command register enables FIS delivery to the device. If this bit is low, the HBA will ignore anything you send to it.
As I said in the beginning, I'm not sure if this will answer all of your question but I hope that it does get you on the right track. I'm going from memory on the events that must be done in order to effectively communicate to a SATA device. I may not have remembered in full detail.
I hope this helps you.