objective c - Example of using Audio Queue Services -
i seeking example of using audio queue services.
i create sound using mathematical equation , hear it.
here's code generating sound function. i'm assuming know how use audioqueue services, set audiosession, , start , stop audio output queue.
here's snippet setting , starting output audioqueue:
// preferred sample rate (8,000 hz on iphone, 44,100 hz on ipod touch) size = sizeof(samplerate); err = audiosessiongetproperty (kaudiosessionproperty_currenthardwaresamplerate, &size, &samplerate); if (err != noerr) nslog(@"audiosessiongetproperty(kaudiosessionproperty_currenthardwaresamplerate) error: %d", err); //nslog (@"current hardware sample rate: %1.0f", samplerate); bool ishighsamplerate = (samplerate > 16000); int bufferbytesize; audioqueuebufferref buffer; // set stream format fields audiostreambasicdescription streamformat; streamformat.msamplerate = samplerate; streamformat.mformatid = kaudioformatlinearpcm; streamformat.mformatflags = klinearpcmformatflagissignedinteger | klinearpcmformatflagispacked; streamformat.mbitsperchannel = 16; streamformat.mchannelsperframe = 1; streamformat.mbytesperpacket = 2 * streamformat.mchannelsperframe; streamformat.mbytesperframe = 2 * streamformat.mchannelsperframe; streamformat.mframesperpacket = 1; streamformat.mreserved = 0; // new output queue ---- playback ---- if (isplaying == no) { err = audioqueuenewoutput (&streamformat, audioengineoutputbuffercallback, self, nil, nil, 0, &outputqueue); if (err != noerr) nslog(@"audioqueuenewoutput() error: %d", err); // enqueue buffers //outputfrequency = 0.0; outputbufferstorewrite = 3; bufferbytesize = (samplerate > 16000)? 2176 : 512; // 40.5 hz : 31.25 hz (i=0; i<3; i++) { err = audioqueueallocatebuffer (outputqueue, bufferbytesize, &buffer); if (err == noerr) { [self generatetone: buffer]; err = audioqueueenqueuebuffer (outputqueue, buffer, 0, nil); if (err != noerr) nslog(@"audioqueueenqueuebuffer() error: %d", err); } else { nslog(@"audioqueueallocatebuffer() error: %d", err); return; } } // start playback isplaying = yes; err = audioqueuestart(outputqueue, nil); if (err != noerr) { nslog(@"audioqueuestart() error: %d", err); isplaying= no; return; } } else { nslog (@"error: audio playing back."); }
here's part generates tone:
// audioqueue output queue callback. void audioengineoutputbuffercallback (void *inuserdata, audioqueueref inaq, audioqueuebufferref inbuffer) { audioengine *engine = (audioengine*) inuserdata; [engine processoutputbuffer:inbuffer queue:inaq]; } - (void) processoutputbuffer: (audioqueuebufferref) buffer queue:(audioqueueref) queue { osstatus err; if (isplaying == yes) { [outputlock lock]; if (outputbufferstorewrite > 0) { outputbufferstorewrite--; [self generatetone:buffer]; } err = audioqueueenqueuebuffer(queue, buffer, 0, null); if (err == 560030580) { // queue not active due music being started or other reasons isplaying = no; } else if (err != noerr) { nslog(@"audioqueueenqueuebuffer() error %d", err); } [outputlock unlock]; } else { err = audioqueuestop (queue, no); if (err != noerr) nslog(@"audioqueuestop() error: %d", err); } } -(void) generatetone: (audioqueuebufferref) buffer { if (outputfrequency == 0.0) { memset(buffer->maudiodata, 0, buffer->maudiodatabytescapacity); buffer->maudiodatabytesize = buffer->maudiodatabytescapacity; } else { // make buffer length multiple of wavelength output frequency. int samplecount = buffer->maudiodatabytescapacity / sizeof (sint16); double bufferlength = samplecount; double wavelength = samplerate / outputfrequency; double repetitions = floor (bufferlength / wavelength); if (repetitions > 0.0) { samplecount = round (wavelength * repetitions); } double x, y; double sd = 1.0 / samplerate; double amp = 0.9; double max16bit = shrt_max; int i; sint16 *p = buffer->maudiodata; (i = 0; < samplecount; i++) { x = * sd * outputfrequency; switch (outputwaveform) { case ksine: y = sin (x * 2.0 * m_pi); break; case ktriangle: x = fmod (x, 1.0); if (x < 0.25) y = x * 4.0; // 0.0 1.0 else if (x < 0.75) y = (1.0 - x) * 4.0 - 2.0; // down 1.0 -1.0 else y = (x - 1.0) * 4.0; // -1.0 0.0 break; case ksawtooth: y = 0.8 - fmod (x, 1.0) * 1.8; break; case ksquare: y = (fmod(x, 1.0) < 0.5)? 0.7: -0.7; break; default: y = 0; break; } p[i] = y * max16bit * amp; } buffer->maudiodatabytesize = samplecount * sizeof (sint16); } }
something watch out callback called on non-main thread, have practice thread safety locks, mutexs, or other techniques.
Comments
Post a Comment