Creating simple waveforms with CoreAudio
Asked Answered
D

5

10

I am new to CoreAudio, and I would like to output a simple sine wave and square wave with a given frequency and amplitude through the speakers using CA. I don't want to use sound files as I want to synthesize the sound.

What do I need to do this? And can you give me an example or tutorial? Thanks.

Dinky answered 10/6, 2010 at 21:1 Comment(0)
D
16

There are a number of errors in the previous answer. I, the legendary :-) James McCartney, not James Harkins wrote the sinewavedemo, I also wrote SuperCollider which is what the audiosynth.com website is about. I also now work at Apple on CoreAudio. The sinewavedemo DOES use CoreAudio, since it uses AudioHardware.h from CoreAudio.framework as its way to play the sound.

You should not use the sinewavedemo. It is very old code and it makes dangerous assumptions about the buffer layout of the audio hardware. The easiest way nowadays to play a sound that you are generating is to use the AudioQueue, or to use an output audio unit with a render callback set.

Democritus answered 21/3, 2011 at 15:35 Comment(1)
Any advice where and how to start to "Creating simple waveforms with CoreAudio"?Techy
F
1

Are you new to audio programming in general? As a starting point i would check out

http://www.audiosynth.com/sinewavedemo.html

This is a minimum osx sinewave implementation by the legendary James Harkins. Note, it doesn't use CoreAudio at all.

If you specifically want to use CoreAudio for your sinewave you need to create an output unit (RemoteIO on the iphone, AUHAL on osx) and supply an input callback, where you can pretty much use the code from the above example. Check out

http://developer.apple.com/mac/library/technotes/tn2002/tn2091.html

The benefits of CoreAudio are chiefly, chain other effects with your sinewave, write plugins for hosts like Logic & provide the interfaces for them, write a host (like Logic) for plugins that can be chained together.

If you don't wont to write a plugin, or host plugins then CoreAudio might not actually be for you. But one of the best things about using CoreAudio is that once you get your sinewave callback working it is easy to add effects, or mix multiple sines together

To do this you need to put your output unit in a graph, to which you can effects, mixers, etc.

Here is some help on setting up graphs http://timbolstad.com/2010/03/16/core-audio-getting-started-pt2/

It isn't as difficult as it looks. Apple provides C++ helper classes for many things (/Developer/Examples/CoreAudio/PublicUtility) and even if you don't want to use C++ (you don't have to!) they can be a useful guide to the CoreAudio API.

Fluid answered 10/6, 2010 at 23:17 Comment(2)
Mmm.. The first example (audiosynth.com...) gives 11415 compile errors and it is quite old (Project Builder), but I'll take a look at it's source code. ThanksDinky
Yes it is quite old but it's not too difficult to get working (i have it running here) and it is an invaluable insight into low-level audio on OSXFluid
E
1

If you are not doing this realtime, using the sin() function from math.h is not a bad idea. Just fill however many samples you need with sin() beforehand when it is time to play it, just send it to the audio buffer. sin() can be quite slow to call once every sample if you are doing this realtime, using an interpolated wavetable lookup method is much faster, but the resulting sound will not be as spectrally pure.

Ectomy answered 27/12, 2012 at 19:9 Comment(0)
B
1

The best and easiest way to do that without files is to prepare a single cycle buffer, containing one cycle of the wave (this is called technically a wavetable)

In the playback function called by CoreAudio thread, fill the output buffer with samples read from the wave buffer.

Note however that you will face two problems very quickly : - for the sine wave, if the playback frequency is not an integer multiple of the desired sine frequency, you will probably need to implement an interpolator if you want to have a good quality. Using only integer pointers will generate a significant level of harmonic noise.

  • for the square wave, avoid to just program an array with +1 / -1 values. Such a signal is not bandlimited and will alias a lot. Do not forget that the spectrum of a square wave is virtually infinite!

To get good algorithms for signal generation, take a look to musicdsp.org, that's probably one of the best resource for that

Boswall answered 1/1, 2015 at 9:24 Comment(0)
D
0

There is a good and well documented sine wave player code example in Chapter 7 of the Adamson/Avila "Learning Core Audio" book, published by Addison-Wesley Professional (ISBN-10: 0-321-63684-8 ):

http://www.informit.com/store/learning-core-audio-a-hands-on-guide-to-audio-programming-9780321636843

It is a rather new publication (2012) and addresses precisely the issue of this question. It's only a starting point, but it's a valuable starting point.

BTW. Don't jump to graphs before having this basic lesson (which involves some math) behind.

Concerning example code, a quick and efficient method I often use deals with a pre-filled sinewave lookup table which has as many members as sample rate, for 44100 Hz the table has size of 44100. In other words, cycle length equals sample rate. This gives an acceptable trade-off between speed and quality in many cases. You can initialize it with the program.
If you generate floating point samples (which is default in OSX), and use math functions, use sinf() rather than (float)sin(). Promotions in inner loop cycles of a render callback are always resource-expensive. So are repetitive multiplications of constants, such as 2.0*M_PI, which can too often be found in code examples.

Dam answered 8/1, 2015 at 14:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.