I am wondering if anyone has come across a way to generate tones in the iPhone SDK. I am trying to generate DTMF tones, and can't seem to find anything substantial out there. I want to be able to specify how long to play the tone for as well (i.e. to simulate holding the button down as opposed to just pressing it briefly..
I found an open source app called iPhreak. It supposedly generates DTMF tones to fool payphones (I Assure you this is not my intention - my company deals with telephone based Intercom systems). The only problem with that application is that there are files missing from the open source project. Perhaps someone else has gotten this project to work in the past?
If anyone has any idea on where I would look for something like this, I would be very appreciative with my votes :)
should be easy enough to generate yourself.
given that the hardware can playback a pcm buffer (16bit samples) at 44.1 khz (which it surely can with some library function or the other), you're only left with calculating the waveform:
const int PLAYBACKFREQ = 44100;
const float PI2 = 3.14159265359f * 2;
void generateDTMF(short *buffer, int length, float freq1, float freq2)
{
int i;
short *dest = buffer;
for(i=0; i<length; i++)
{
*(dest++) = (sin(i*(PI2*(PLAYBACKFREQ/freq1))) + sin(i (PI2*(PLAYBACKFREQ/freq2)))) * 16383;
}
}
the 16383 is done since I'm using additive synthesis (just adding the sinewaves together). Therefore the max result is -2.0 - 2.0 So after multiplying by 16383 I get more or less the max 16 bit result: -32768 - +32767
EDIT:
the 2 frequenties are the frequenties from the wikipedia article the other person who answered linked to. Two unique frequencies make a DTMF sound
The easy answer is this:
soundArray = [[NSArray alloc] initWithObjects:
[[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-0.caf"] autorelease],
[[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-1.caf"] autorelease],
[[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-2.caf"] autorelease],
[[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-3.caf"] autorelease],
[[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-4.caf"] autorelease],
[[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-5.caf"] autorelease],
[[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-6.caf"] autorelease],
[[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-7.caf"] autorelease],
[[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-8.caf"] autorelease],
[[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-9.caf"] autorelease],
[[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-0.caf"] autorelease],
[[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-pound.caf"] autorelease],
[[[SoundEffect alloc] initWithContentsOfFile: @"/System/Library/Audio/UISounds/dtmf-star.caf"] autorelease],
nil];
There you have it. All the sounds of a standard phone keypad, in an array, ready for your enjoyment.
Swift DTMF Sounds
I was experimenting with generating PCM data and came up with this in Swift. This function will generate an [Float]
which are the audio samples. You can play them with AVAudio
.
Each DTMF is comprised of a pair of tones, a mark length (250 ms), a space length (250 ms), and of course you need to specify a sample frequency (8000 Hz). Mark and Space are usually around 250 ms for what I would call standard human dialing. The sample frequency is fun to play with, but needs to be twice the highest frequency. For fun you can drop it below that to hear what happens.
public static func generateDTMF(frequency1 frequency1: Float, frequency2: Float, markSpace: MarkSpaceType, sampleRate: Float) -> [Float]
{
let toneLengthInSamples = 10e-4 * markSpace.0 * sampleRate
let silenceLengthInSamples = 10e-4 * markSpace.1 * sampleRate
var sound = [Float](count: Int(toneLengthInSamples + silenceLengthInSamples), repeatedValue: 0)
let twoPI = 2.0 * Float(M_PI)
for i in 0 ..< Int(toneLengthInSamples) {
// Add first tone at half volume
let sample1 = 0.5 * sin(Float(i) * twoPI / (sampleRate / frequency1));
// Add second tone at half volume
let sample2 = 0.5 * sin(Float(i) * twoPI / (sampleRate / frequency2));
sound[i] = sample1 + sample2
}
return sound
}
The full Playground can be downloaded on GitHub.