source: mediastreamer2/src/aqsnd.c @ 947:d2ba2ac865ab

Last change on this file since 947:d2ba2ac865ab was 947:d2ba2ac865ab, checked in by Aymeric Moizard <jack@…>, 3 years ago

add support for volume control in AudioUnit?

File size: 28.6 KB
Line 
1/*
2mediastreamer2 library - modular sound and video processing and streaming
3Copyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)
4
5This program is free software; you can redistribute it and/or
6modify it under the terms of the GNU General Public License
7as published by the Free Software Foundation; either version 2
8of the License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18*/
19
20/* this file is specifically distributed under a BSD license */
21
22/**
23* Copyright (C) 2008  Hiroki Mori (himori@users.sourceforge.net)
24* All rights reserved.
25*
26* Redistribution and use in source and binary forms, with or without
27* modification, are permitted provided that the following conditions are met:
28*     * Redistributions of source code must retain the above copyright
29*       notice, this list of conditions and the following disclaimer.
30*     * Redistributions in binary form must reproduce the above copyright
31*       notice, this list of conditions and the following disclaimer in the
32*       documentation and/or other materials provided with the distribution.
33*     * Neither the name of the <organization> nor the
34*       names of its contributors may be used to endorse or promote products
35*       derived from this software without specific prior written permission.
36*
37* THIS SOFTWARE IS PROVIDED BY <copyright holder> ``AS IS'' AND ANY
38* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
39* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40* DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
41* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47**/
48
49/*
50 This is MacOS X Audio Queue Service support code for mediastreamer2.
51 Audio Queue Support MacOS X 10.5 or later.
52 http://developer.apple.com/documentation/MusicAudio/Conceptual/AudioQueueProgrammingGuide/
53 */
54
55#ifdef __APPLE__
56#include "TargetConditionals.h"
57#endif
58
59#include <AudioToolbox/AudioToolbox.h>
60#ifndef TARGET_OS_IPHONE
61#include <CoreAudio/AudioHardware.h>
62#endif
63
64#include "mediastreamer2/mssndcard.h"
65#include "mediastreamer2/msfilter.h"
66
67MSFilter *ms_aq_read_new(MSSndCard * card);
68MSFilter *ms_aq_write_new(MSSndCard * card);
69
70#define kSecondsPerBuffer               0.02    /*0.04 */
71#define kNumberAudioOutDataBuffers      4
72#define kNumberAudioInDataBuffers       4
73
74static float gain_volume_in=1.0;
75static float gain_volume_out=1.0;
76static bool gain_changed_in = true;
77static bool gain_changed_out = true;
78
79#ifdef TARGET_OS_IPHONE
80#define CFStringRef void *
81#define CFRelease(A) {}
82#define CFStringGetCString(A, B, LEN, encoding)  {}
83#define CFStringCreateCopy(A, B) NULL
84#endif
85
86typedef struct AQData {
87        CFStringRef uidname;
88        AudioStreamBasicDescription devicereadFormat;
89        AudioStreamBasicDescription devicewriteFormat;
90
91        int rate;
92        int bits;
93        bool_t stereo;
94
95        ms_mutex_t mutex;
96        queue_t rq;
97        bool_t read_started;
98        bool_t write_started;
99#if 0
100        AudioConverterRef readAudioConverter;
101#endif
102        AudioQueueRef readQueue;
103        AudioStreamBasicDescription readAudioFormat;
104        UInt32 readBufferByteSize;
105
106#if 0
107        AudioConverterRef writeAudioConverter;
108#endif
109        AudioQueueRef writeQueue;
110        AudioStreamBasicDescription writeAudioFormat;
111        UInt32 writeBufferByteSize;
112        AudioQueueBufferRef writeBuffers[kNumberAudioOutDataBuffers];
113        int curWriteBuffer;
114        MSBufferizer *bufferizer;
115} AQData;
116
117
118
119/*
120 mediastreamer2 function
121 */
122
123typedef struct AqSndDsCard {
124        CFStringRef uidname;
125        AudioStreamBasicDescription devicereadFormat;
126        AudioStreamBasicDescription devicewriteFormat;
127        int removed;
128} AqSndDsCard;
129
130static void aqcard_set_level(MSSndCard * card, MSSndCardMixerElem e,
131                                                         int percent)
132{
133        switch(e){
134                case MS_SND_CARD_PLAYBACK:
135                case MS_SND_CARD_MASTER:
136                        gain_volume_out =((float)percent)/100.0f;
137                        gain_changed_out = true;
138                        return;
139                case MS_SND_CARD_CAPTURE:
140                        gain_volume_in =((float)percent)/100.0f;
141                        gain_changed_in = true;
142                        return;
143                default:
144                        ms_warning("aqcard_set_level: unsupported command.");
145        }
146}
147
148static int aqcard_get_level(MSSndCard * card, MSSndCardMixerElem e)
149{
150        switch(e){
151                case MS_SND_CARD_PLAYBACK:
152                case MS_SND_CARD_MASTER:
153                  return (int)(gain_volume_out*100.0f);
154                case MS_SND_CARD_CAPTURE:
155                  return (int)(gain_volume_in*100.0f);
156                default:
157                        ms_warning("aqcard_get_level: unsupported command.");
158        }
159        return -1;
160}
161
162static void aqcard_set_source(MSSndCard * card, MSSndCardCapture source)
163{
164}
165
166static void aqcard_init(MSSndCard * card)
167{
168        AqSndDsCard *c = (AqSndDsCard *) ms_new0(AqSndDsCard, 1);
169        c->removed = 0;
170        card->data = c;
171}
172
173static void aqcard_uninit(MSSndCard * card)
174{
175        AqSndDsCard *d = (AqSndDsCard *) card->data;
176        if (d->uidname != NULL)
177                CFRelease(d->uidname);
178        ms_free(d);
179}
180
181static void aqcard_detect(MSSndCardManager * m);
182static MSSndCard *aqcard_duplicate(MSSndCard * obj);
183
184MSSndCardDesc aq_card_desc = {
185        .driver_type = "AQ",
186        .detect = aqcard_detect,
187        .init = aqcard_init,
188        .set_level = aqcard_set_level,
189        .get_level = aqcard_get_level,
190        .set_capture = aqcard_set_source,
191        .set_control = NULL,
192        .get_control = NULL,
193        .create_reader = ms_aq_read_new,
194        .create_writer = ms_aq_write_new,
195        .uninit = aqcard_uninit,
196        .duplicate = aqcard_duplicate
197};
198
199static MSSndCard *aqcard_duplicate(MSSndCard * obj)
200{
201        AqSndDsCard *ca;
202        AqSndDsCard *cadup;
203        MSSndCard *card = ms_snd_card_new(&aq_card_desc);
204        card->name = ms_strdup(obj->name);
205        card->data = ms_new0(AqSndDsCard, 1);
206        memcpy(card->data, obj->data, sizeof(AqSndDsCard));
207        ca = obj->data;
208        cadup = card->data;
209        cadup->uidname = CFStringCreateCopy(NULL, ca->uidname);
210        return card;
211}
212
213static MSSndCard *aq_card_new(const char *name, CFStringRef uidname,
214                                                          AudioStreamBasicDescription *
215                                                          devicereadFormat,
216                                                          AudioStreamBasicDescription *
217                                                          devicewriteFormat, unsigned cap)
218{
219        MSSndCard *card = ms_snd_card_new(&aq_card_desc);
220        AqSndDsCard *d = (AqSndDsCard *) card->data;
221        d->uidname = uidname;
222        if (devicereadFormat!=NULL)
223          memcpy(&d->devicereadFormat, devicereadFormat,
224                 sizeof(AudioStreamBasicDescription));
225        if (devicewriteFormat!=NULL)
226          memcpy(&d->devicewriteFormat, devicewriteFormat,
227                 sizeof(AudioStreamBasicDescription));
228        card->name = ms_strdup(name);
229        card->capabilities = cap;
230        return card;
231}
232
233static void show_format(char *name,
234                                                AudioStreamBasicDescription * deviceFormat)
235{
236        ms_message("Format for %s", name);
237        ms_message("mSampleRate = %g", deviceFormat->mSampleRate);
238        char *the4CCString = (char *) &deviceFormat->mFormatID;
239        char outName[5];
240        outName[0] = the4CCString[0];
241        outName[1] = the4CCString[1];
242        outName[2] = the4CCString[2];
243        outName[3] = the4CCString[3];
244        outName[4] = 0;
245        ms_message("mFormatID = %s", outName);
246        ms_message("mFormatFlags = %08lX", deviceFormat->mFormatFlags);
247        ms_message("mBytesPerPacket = %ld", deviceFormat->mBytesPerPacket);
248        ms_message("mFramesPerPacket = %ld", deviceFormat->mFramesPerPacket);
249        ms_message("mChannelsPerFrame = %ld", deviceFormat->mChannelsPerFrame);
250        ms_message("mBytesPerFrame = %ld", deviceFormat->mBytesPerFrame);
251        ms_message("mBitsPerChannel = %ld", deviceFormat->mBitsPerChannel);
252}
253
254static void aqcard_detect(MSSndCardManager * m)
255{
256#ifndef TARGET_OS_IPHONE
257        OSStatus err;
258        UInt32 slen;
259        int count;
260        Boolean writable;
261        int i;
262        writable = 0;
263        slen = 0;
264        err =
265                AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &slen,
266                                                                         &writable);
267        if (err != kAudioHardwareNoError) {
268                ms_error("get kAudioHardwarePropertyDevices error %ld", err);
269                return;
270        }
271        AudioDeviceID V[slen / sizeof(AudioDeviceID)];
272        err =
273                AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &slen, V);
274        if (err != kAudioHardwareNoError) {
275                ms_error("get kAudioHardwarePropertyDevices error %ld", err);
276                return;
277        }
278        count = slen / sizeof(AudioDeviceID);
279        for (i = 0; i < count; i++) {
280                char devname_in[256];
281                char uidname_in[256];
282                char devname_out[256];
283                char uidname_out[256];
284                int cap = 0;
285
286                /* OUTPUT CARDS */
287                slen = 256;
288                err =
289                        AudioDeviceGetProperty(V[i], 0, FALSE,
290                                                                   kAudioDevicePropertyDeviceName, &slen,
291                                                                   devname_out);
292                if (err != kAudioHardwareNoError) {
293                        ms_error("get kAudioDevicePropertyDeviceName error %ld", err);
294                        continue;
295                }
296                slen = strlen(devname_out);
297                /* trim whitespace */
298                while ((slen > 0) && (devname_out[slen - 1] == ' ')) {
299                        slen--;
300                }
301                devname_out[slen] = '\0';
302
303                err =
304                        AudioDeviceGetPropertyInfo(V[i], 0, FALSE,
305                                                                           kAudioDevicePropertyStreamConfiguration,
306                                                                           &slen, &writable);
307                if (err != kAudioHardwareNoError) {
308                        ms_error("get kAudioDevicePropertyDeviceName error %ld", err);
309                        continue;
310                }
311
312                AudioBufferList *buflist = ms_malloc(slen);
313                if (buflist == NULL) {
314                        ms_error("alloc AudioBufferList %ld", err);
315                        continue;
316                }
317
318                err =
319                        AudioDeviceGetProperty(V[i], 0, FALSE,
320                                                                   kAudioDevicePropertyStreamConfiguration,
321                                                                   &slen, buflist);
322                if (err != kAudioHardwareNoError) {
323                        ms_error("get kAudioDevicePropertyDeviceName error %ld", err);
324                        ms_free(buflist);
325                        continue;
326                }
327
328                UInt32 j;
329                for (j = 0; j < buflist->mNumberBuffers; j++) {
330                        if (buflist->mBuffers[j].mNumberChannels > 0) {
331                                cap = MS_SND_CARD_CAP_PLAYBACK;
332                                break;
333                        }
334                }
335
336                ms_free(buflist);
337
338                /* INPUT CARDS */
339                slen = 256;
340                err =
341                        AudioDeviceGetProperty(V[i], 0, TRUE,
342                                                                   kAudioDevicePropertyDeviceName, &slen,
343                                                                   devname_in);
344                if (err != kAudioHardwareNoError) {
345                        ms_error("get kAudioDevicePropertyDeviceName error %ld", err);
346                        continue;
347                }
348                slen = strlen(devname_in);
349                /* trim whitespace */
350                while ((slen > 0) && (devname_in[slen - 1] == ' ')) {
351                        slen--;
352                }
353                devname_in[slen] = '\0';
354
355                err =
356                        AudioDeviceGetPropertyInfo(V[i], 0, TRUE,
357                                                                           kAudioDevicePropertyStreamConfiguration,
358                                                                           &slen, &writable);
359                if (err != kAudioHardwareNoError) {
360                        ms_error("get kAudioDevicePropertyDeviceName error %ld", err);
361                        continue;
362                }
363
364
365                err =
366                        AudioDeviceGetPropertyInfo(V[i], 0, TRUE,
367                                                                           kAudioDevicePropertyStreamConfiguration,
368                                                                           &slen, &writable);
369                if (err != kAudioHardwareNoError) {
370                        ms_error("get kAudioDevicePropertyDeviceName error %ld", err);
371                        continue;
372                }
373                buflist = ms_malloc(slen);
374                if (buflist == NULL) {
375                        ms_error("alloc error %ld", err);
376                        continue;
377                }
378
379                err =
380                        AudioDeviceGetProperty(V[i], 0, TRUE,
381                                                                   kAudioDevicePropertyStreamConfiguration,
382                                                                   &slen, buflist);
383                if (err != kAudioHardwareNoError) {
384                        ms_error("get kAudioDevicePropertyDeviceName error %ld", err);
385                        ms_free(buflist);
386                        continue;
387                }
388
389                for (j = 0; j < buflist->mNumberBuffers; j++) {
390                        if (buflist->mBuffers[j].mNumberChannels > 0) {
391                                cap |= MS_SND_CARD_CAP_CAPTURE;
392                                break;
393                        }
394                }
395
396                ms_free(buflist);
397
398                if (cap & MS_SND_CARD_CAP_PLAYBACK) {
399                  CFStringRef dUID_out;
400                  dUID_out = NULL;
401                  slen = sizeof(CFStringRef);
402                  err =
403                    AudioDeviceGetProperty(V[i], 0, false,
404                                           kAudioDevicePropertyDeviceUID, &slen,
405                                           &dUID_out);
406                  if (err != kAudioHardwareNoError) {
407                    ms_error("get kAudioHardwarePropertyDevices error %ld", err);
408                    continue;
409                  }
410                  CFStringGetCString(dUID_out, uidname_out, 256,
411                                     CFStringGetSystemEncoding());
412                  ms_message("AQ: devname_out:%s uidname_out:%s", devname_out, uidname_out);
413
414                  AudioStreamBasicDescription devicewriteFormat;
415                  slen = sizeof(devicewriteFormat);
416                  err = AudioDeviceGetProperty(V[i], 0, false,
417                                               kAudioDevicePropertyStreamFormat,
418                                               &slen, &devicewriteFormat);
419                  if (err == kAudioHardwareNoError) {
420                    show_format("output device", &devicewriteFormat);
421                  }
422                  MSSndCard *card = aq_card_new(devname_out, dUID_out, NULL,
423                                                &devicewriteFormat, MS_SND_CARD_CAP_PLAYBACK);
424                  ms_snd_card_manager_add_card(m, card);
425                }
426
427                if (cap & MS_SND_CARD_CAP_CAPTURE) {
428                  CFStringRef dUID_in;
429                  dUID_in = NULL;
430                  slen = sizeof(CFStringRef);
431                  err =
432                    AudioDeviceGetProperty(V[i], 0, true,
433                                           kAudioDevicePropertyDeviceUID, &slen,
434                                           &dUID_in);
435                  if (err != kAudioHardwareNoError) {
436                    ms_error("get kAudioHardwarePropertyDevices error %ld", err);
437                    continue;
438                  }
439                  CFStringGetCString(dUID_in, uidname_in, 256,
440                                     CFStringGetSystemEncoding());
441                  ms_message("AQ: devname_in:%s uidname_in:%s", devname_in, uidname_in);
442                 
443                  AudioStreamBasicDescription devicereadFormat;
444                  slen = sizeof(devicereadFormat);
445                  err = AudioDeviceGetProperty(V[i], 0, true,
446                                               kAudioDevicePropertyStreamFormat,
447                                               &slen, &devicereadFormat);
448                  if (err == kAudioHardwareNoError) {
449                    show_format("input device", &devicereadFormat);
450                  }
451                  MSSndCard *card = aq_card_new(devname_in, dUID_in, &devicereadFormat,
452                                                NULL, MS_SND_CARD_CAP_CAPTURE);
453                  ms_snd_card_manager_add_card(m, card);
454                }
455        }
456#else
457        AudioStreamBasicDescription deviceFormat;
458        memset(&deviceFormat, 0, sizeof(AudioStreamBasicDescription));
459
460        MSSndCard *card = aq_card_new("Audio Queue Device", NULL, &deviceFormat,
461                                                                  &deviceFormat, MS_SND_CARD_CAP_PLAYBACK|MS_SND_CARD_CAP_CAPTURE);
462        ms_snd_card_manager_add_card(m, card);
463#endif
464}
465
466
467/*
468 Audio Queue recode callback
469 */
470
471static void readCallback(void *aqData,
472                                                 AudioQueueRef inAQ,
473                                                 AudioQueueBufferRef inBuffer,
474                                                 const AudioTimeStamp * inStartTime,
475                                                 UInt32 inNumPackets,
476                                                 const AudioStreamPacketDescription * inPacketDesc)
477{
478        AQData *d = (AQData *) aqData;
479        OSStatus err;
480        mblk_t *rm = NULL;
481
482        UInt32 len =
483                (inBuffer->mAudioDataByteSize * d->readAudioFormat.mSampleRate /
484                 1) / d->devicereadFormat.mSampleRate /
485                d->devicereadFormat.mChannelsPerFrame;
486
487        ms_mutex_lock(&d->mutex);
488        if (d->read_started == FALSE) {
489                ms_mutex_unlock(&d->mutex);
490                return;
491        }
492
493        rm = allocb(len, 0);
494
495#if 0
496        err = AudioConverterConvertBuffer(d->readAudioConverter,
497                                                                          inBuffer->mAudioDataByteSize,
498                                                                          inBuffer->mAudioData,
499                                                                          &len, rm->b_wptr);
500        if (err != noErr) {
501                ms_error("readCallback: AudioConverterConvertBuffer %d", err);
502                ms_warning("readCallback: inBuffer->mAudioDataByteSize = %d",
503                                   inBuffer->mAudioDataByteSize);
504                ms_warning("readCallback: outlen = %d", len);
505                ms_warning("readCallback: origlen = %i",
506                                   (inBuffer->mAudioDataByteSize *
507                                        d->readAudioFormat.mSampleRate / 1) /
508                                   d->devicereadFormat.mSampleRate /
509                                   d->devicereadFormat.mChannelsPerFrame);
510                freeb(rm);
511        } else {
512
513          rm->b_wptr += len;
514          if (gain_volume_in != 1.0f)
515            {
516              int16_t *ptr=(int16_t *)rm->b_rptr;
517              for (;ptr<(int16_t *)rm->b_wptr;ptr++)
518                {
519                  *ptr=(int16_t)(((float)(*ptr))*gain_volume_in);
520                }
521            }
522          putq(&d->rq, rm);
523        }
524#else
525        memcpy(rm->b_wptr, inBuffer->mAudioData, len);
526        rm->b_wptr += len;
527        if (gain_volume_in != 1.0f)
528        {
529                int16_t *ptr=(int16_t *)rm->b_rptr;
530                for (;ptr<(int16_t *)rm->b_wptr;ptr++)
531                {
532                        *ptr=(int16_t)(((float)(*ptr))*gain_volume_in);
533                }
534        }
535        putq(&d->rq, rm);       
536#endif
537       
538        err = AudioQueueEnqueueBuffer(d->readQueue, inBuffer, 0, NULL);
539        if (err != noErr) {
540                ms_error("readCallback:AudioQueueEnqueueBuffer %d", err);
541        }
542        ms_mutex_unlock(&d->mutex);
543}
544
545/*
546 Audio Queue play callback
547 */
548
549static void writeCallback(void *aqData,
550                                                  AudioQueueRef inAQ, AudioQueueBufferRef inBuffer)
551{
552        AQData *d = (AQData *) aqData;
553        OSStatus err;
554
555        int len =
556                (d->writeBufferByteSize * d->writeAudioFormat.mSampleRate / 1) /
557                d->devicewriteFormat.mSampleRate /
558                d->devicewriteFormat.mChannelsPerFrame;
559
560        ms_mutex_lock(&d->mutex);
561        if (d->write_started == FALSE) {
562                ms_mutex_unlock(&d->mutex);
563                return;
564        }
565        if (d->bufferizer->size >= len) {
566#if 0
567                UInt32 bsize = d->writeBufferByteSize;
568                uint8_t *pData = ms_malloc(len);
569
570                ms_bufferizer_read(d->bufferizer, pData, len);
571                err = AudioConverterConvertBuffer(d->writeAudioConverter,
572                                                                                  len,
573                                                                                  pData,
574                                                                                  &bsize, inBuffer->mAudioData);
575                if (err != noErr) {
576                        ms_error("writeCallback: AudioConverterConvertBuffer %d", err);
577                }
578                ms_free(pData);
579
580                if (bsize != d->writeBufferByteSize)
581                        ms_warning("d->writeBufferByteSize = %i len = %i bsize = %i",
582                                           d->writeBufferByteSize, len, bsize);
583#else
584                ms_bufferizer_read(d->bufferizer, inBuffer->mAudioData, len);
585#endif
586        } else {
587                memset(inBuffer->mAudioData, 0, d->writeBufferByteSize);
588        }
589        inBuffer->mAudioDataByteSize = d->writeBufferByteSize;
590
591        if (gain_changed_out == true)
592          {
593            AudioQueueSetParameter (d->writeQueue,
594                                    kAudioQueueParam_Volume,
595                                    gain_volume_out);
596            gain_changed_out = false;
597          }
598
599        err = AudioQueueEnqueueBuffer(d->writeQueue, inBuffer, 0, NULL);
600        if (err != noErr) {
601                ms_error("AudioQueueEnqueueBuffer %d", err);
602        }
603        ms_mutex_unlock(&d->mutex);
604}
605
606void putWriteAQ(void *aqData, int queuenum)
607{
608        AQData *d = (AQData *) aqData;
609        OSStatus err;
610        err = AudioQueueEnqueueBuffer(d->writeQueue,
611                                                                  d->writeBuffers[queuenum], 0, NULL);
612        if (err != noErr) {
613                ms_error("AudioQueueEnqueueBuffer %d", err);
614        }
615}
616
617/*
618 play buffer setup function
619 */
620
621void setupWrite(MSFilter * f)
622{
623        AQData *d = (AQData *) f->data;
624        OSStatus err;
625
626        int bufferIndex;
627
628        for (bufferIndex = 0; bufferIndex < kNumberAudioOutDataBuffers;
629                 ++bufferIndex) {
630
631                err = AudioQueueAllocateBuffer(d->writeQueue,
632                                                                           d->writeBufferByteSize,
633                                                                           &d->writeBuffers[bufferIndex]
634                        );
635                if (err != noErr) {
636                        ms_error("setupWrite:AudioQueueAllocateBuffer %d", err);
637                }
638        }
639}
640
641/*
642 recode buffer setup function
643 */
644
645void setupRead(MSFilter * f)
646{
647        AQData *d = (AQData *) f->data;
648        OSStatus err;
649
650        // allocate and enqueue buffers
651        int bufferIndex;
652
653        for (bufferIndex = 0; bufferIndex < kNumberAudioInDataBuffers;
654                 ++bufferIndex) {
655
656                AudioQueueBufferRef buffer;
657
658                err = AudioQueueAllocateBuffer(d->readQueue,
659                                                                           d->readBufferByteSize, &buffer);
660                if (err != noErr) {
661                        ms_error("setupRead:AudioQueueAllocateBuffer %d", err);
662                }
663
664                err = AudioQueueEnqueueBuffer(d->readQueue, buffer, 0, NULL);
665                if (err != noErr) {
666                        ms_error("AudioQueueEnqueueBuffer %d", err);
667                }
668        }
669}
670
671
672static void aq_start_r(MSFilter * f)
673{
674        AQData *d = (AQData *) f->data;
675        if (d->read_started == FALSE) {
676                OSStatus aqresult;
677
678                d->readAudioFormat.mSampleRate = d->rate;
679                d->readAudioFormat.mFormatID = kAudioFormatLinearPCM;
680                d->readAudioFormat.mFormatFlags =
681                        kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
682                d->readAudioFormat.mFramesPerPacket = 1;
683                d->readAudioFormat.mChannelsPerFrame = 1;
684                d->readAudioFormat.mBitsPerChannel = d->bits;
685                d->readAudioFormat.mBytesPerPacket = d->bits / 8;
686                d->readAudioFormat.mBytesPerFrame = d->bits / 8;
687
688                //show_format("input device", &d->devicereadFormat);
689                //show_format("data from input filter", &d->readAudioFormat);
690
691                memcpy(&d->devicereadFormat, &d->readAudioFormat,
692                           sizeof(d->readAudioFormat));
693                d->readBufferByteSize =
694                        kSecondsPerBuffer * d->devicereadFormat.mSampleRate *
695                        (d->devicereadFormat.mBitsPerChannel / 8) *
696                        d->devicereadFormat.mChannelsPerFrame;
697
698#if 0
699                aqresult = AudioConverterNew(&d->devicereadFormat,
700                                                                         &d->readAudioFormat,
701                                                                         &d->readAudioConverter);
702                if (aqresult != noErr) {
703                        ms_error("d->readAudioConverter = %d", aqresult);
704                        d->readAudioConverter = NULL;
705                }
706#endif
707               
708                aqresult = AudioQueueNewInput(&d->devicereadFormat, readCallback, d,    // userData
709                                                                          NULL, // run loop
710                                                                          NULL, // run loop mode
711                                                                          0,    // flags
712                                                                          &d->readQueue);
713                if (aqresult != noErr) {
714                        ms_error("AudioQueueNewInput = %d", aqresult);
715                }
716
717                if (d->uidname!=NULL){
718                        char uidname[256];
719                        CFStringGetCString(d->uidname, uidname, 256,
720                                                           CFStringGetSystemEncoding());
721                        ms_message("AQ: using uidname:%s", uidname);
722                        aqresult =
723                                AudioQueueSetProperty(d->readQueue,
724                                                                  kAudioQueueProperty_CurrentDevice,
725                                                                  &d->uidname, sizeof(CFStringRef));
726                        if (aqresult != noErr) {
727                                ms_error
728                                        ("AudioQueueSetProperty on kAudioQueueProperty_CurrentDevice %d",
729                                         aqresult);
730                        }
731                }
732
733                setupRead(f);
734                aqresult = AudioQueueStart(d->readQueue, NULL); // start time. NULL means ASAP.
735                if (aqresult != noErr) {
736                        ms_error("AudioQueueStart -read- %d", aqresult);
737                }
738                d->read_started = TRUE;
739        }
740}
741
742static void aq_stop_r(MSFilter * f)
743{
744        AQData *d = (AQData *) f->data;
745
746        if (d->read_started == TRUE) {
747                ms_mutex_lock(&d->mutex);
748                d->read_started = FALSE;        /* avoid a deadlock related to buffer conversion in callback  */
749                ms_mutex_unlock(&d->mutex);
750#if 0
751                AudioConverterDispose(d->readAudioConverter);
752#endif
753                AudioQueueStop(d->readQueue, true);
754                AudioQueueDispose(d->readQueue, true);
755        }
756}
757
758static void aq_start_w(MSFilter * f)
759{
760        AQData *d = (AQData *) f->data;
761        if (d->write_started == FALSE) {
762                OSStatus aqresult;
763
764                d->writeAudioFormat.mSampleRate = d->rate;
765                d->writeAudioFormat.mFormatID = kAudioFormatLinearPCM;
766                d->writeAudioFormat.mFormatFlags =
767                        kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
768                d->writeAudioFormat.mFramesPerPacket = 1;
769                d->writeAudioFormat.mChannelsPerFrame = 1;
770                d->writeAudioFormat.mBitsPerChannel = d->bits;
771                d->writeAudioFormat.mBytesPerPacket = d->bits / 8;
772                d->writeAudioFormat.mBytesPerFrame = d->bits / 8;
773
774                show_format("data provided to output filter",   &d->writeAudioFormat);
775                show_format("output device", &d->devicewriteFormat);
776
777                memcpy(&d->devicewriteFormat, &d->writeAudioFormat,
778                           sizeof(d->writeAudioFormat));
779                d->writeBufferByteSize =
780                        kSecondsPerBuffer * d->devicewriteFormat.mSampleRate *
781                        (d->devicewriteFormat.mBitsPerChannel / 8) *
782                        d->devicewriteFormat.mChannelsPerFrame;
783
784#if 0
785                aqresult = AudioConverterNew(&d->writeAudioFormat,
786                                                                         &d->devicewriteFormat,
787                                                                         &d->writeAudioConverter);
788                if (aqresult != noErr) {
789                        ms_error("d->writeAudioConverter = %d", aqresult);
790                        d->writeAudioConverter = NULL;
791                }
792#endif
793               
794                // create the playback audio queue object
795                aqresult = AudioQueueNewOutput(&d->devicewriteFormat, writeCallback, d, NULL,   /*CFRunLoopGetCurrent () */
796                                                                           NULL,        /*kCFRunLoopCommonModes */
797                                                                           0,   // run loop flags
798                                                                           &d->writeQueue);
799                if (aqresult != noErr) {
800                        ms_error("AudioQueueNewOutput = %d", aqresult);
801                }
802
803                AudioQueueSetParameter (d->writeQueue,
804                                        kAudioQueueParam_Volume,
805                                        gain_volume_out);
806
807                if (d->uidname!=NULL){
808                        char uidname[256];
809                        CFStringGetCString(d->uidname, uidname, 256,
810                                                           CFStringGetSystemEncoding());
811                        ms_message("AQ: using uidname:%s", uidname);
812                        aqresult =
813                                AudioQueueSetProperty(d->writeQueue,
814                                                                          kAudioQueueProperty_CurrentDevice,
815                                                                          &d->uidname, sizeof(CFStringRef));
816                        if (aqresult != noErr) {
817                                ms_error
818                                        ("AudioQueueSetProperty on kAudioQueueProperty_CurrentDevice %d",
819                                         aqresult);
820                        }
821                }
822
823                setupWrite(f);
824                d->curWriteBuffer = 0;
825        }
826}
827
828static void aq_stop_w(MSFilter * f)
829{
830        AQData *d = (AQData *) f->data;
831        if (d->write_started == TRUE) {
832                ms_mutex_lock(&d->mutex);
833                d->write_started = FALSE;       /* avoid a deadlock related to buffer conversion in callback */
834                ms_mutex_unlock(&d->mutex);
835#if 0
836                AudioConverterDispose(d->writeAudioConverter);
837#endif
838                AudioQueueStop(d->writeQueue, true);
839
840                AudioQueueDispose(d->writeQueue, true);
841        }
842}
843
844static mblk_t *aq_get(MSFilter * f)
845{
846        AQData *d = (AQData *) f->data;
847        mblk_t *m;
848        ms_mutex_lock(&d->mutex);
849        m = getq(&d->rq);
850        ms_mutex_unlock(&d->mutex);
851        return m;
852}
853
854static void aq_put(MSFilter * f, mblk_t * m)
855{
856        AQData *d = (AQData *) f->data;
857        ms_mutex_lock(&d->mutex);
858        ms_bufferizer_put(d->bufferizer, m);
859        ms_mutex_unlock(&d->mutex);
860
861        int len =
862                (d->writeBufferByteSize * d->writeAudioFormat.mSampleRate / 1) /
863                d->devicewriteFormat.mSampleRate /
864                d->devicewriteFormat.mChannelsPerFrame;
865        if (d->write_started == FALSE && d->bufferizer->size >= len) {
866                AudioQueueBufferRef curbuf = d->writeBuffers[d->curWriteBuffer];
867#if 0
868                OSStatus err;
869                UInt32 bsize = d->writeBufferByteSize;
870                uint8_t *pData = ms_malloc(len);
871
872                ms_bufferizer_read(d->bufferizer, pData, len);
873                err = AudioConverterConvertBuffer(d->writeAudioConverter,
874                                                                                  len,
875                                                                                  pData,
876                                                                                  &bsize, curbuf->mAudioData);
877                if (err != noErr) {
878                        ms_error("writeCallback: AudioConverterConvertBuffer %d", err);
879                }
880                ms_free(pData);
881
882                if (bsize != d->writeBufferByteSize)
883                        ms_warning("d->writeBufferByteSize = %i len = %i bsize = %i",
884                                           d->writeBufferByteSize, len, bsize);
885#else
886                ms_bufferizer_read(d->bufferizer, curbuf->mAudioData, len);
887#endif
888                curbuf->mAudioDataByteSize = d->writeBufferByteSize;
889                putWriteAQ(d, d->curWriteBuffer);
890                ++d->curWriteBuffer;
891        }
892        if (d->write_started == FALSE
893                && d->curWriteBuffer == kNumberAudioOutDataBuffers - 1) {
894                OSStatus err;
895                err = AudioQueueStart(d->writeQueue, NULL       // start time. NULL means ASAP.
896                        );
897                if (err != noErr) {
898                        ms_error("AudioQueueStart -write- %d", err);
899                }
900                d->write_started = TRUE;
901
902        }
903}
904
905static void aq_init(MSFilter * f)
906{
907        AQData *d = ms_new(AQData, 1);
908        d->bits = 16;
909        d->rate = 8000;
910        d->stereo = FALSE;
911
912        d->read_started = FALSE;
913        d->write_started = FALSE;
914        qinit(&d->rq);
915        d->bufferizer = ms_bufferizer_new();
916        ms_mutex_init(&d->mutex, NULL);
917        f->data = d;
918}
919
920static void aq_uninit(MSFilter * f)
921{
922        AQData *d = (AQData *) f->data;
923        flushq(&d->rq, 0);
924        ms_bufferizer_destroy(d->bufferizer);
925        ms_mutex_destroy(&d->mutex);
926        if (d->uidname != NULL)
927                CFRelease(d->uidname);
928        ms_free(d);
929}
930
931static void aq_read_preprocess(MSFilter * f)
932{
933        aq_start_r(f);
934}
935
936static void aq_read_postprocess(MSFilter * f)
937{
938        aq_stop_r(f);
939}
940
941static void aq_read_process(MSFilter * f)
942{
943        mblk_t *m;
944        while ((m = aq_get(f)) != NULL) {
945                ms_queue_put(f->outputs[0], m);
946        }
947}
948
949static void aq_write_preprocess(MSFilter * f)
950{
951        aq_start_w(f);
952}
953
954static void aq_write_postprocess(MSFilter * f)
955{
956        aq_stop_w(f);
957}
958
959static void aq_write_process(MSFilter * f)
960{
961        mblk_t *m;
962        while ((m = ms_queue_get(f->inputs[0])) != NULL) {
963                aq_put(f, m);
964        }
965}
966
967static int set_rate(MSFilter * f, void *arg)
968{
969        AQData *d = (AQData *) f->data;
970        d->rate = *((int *) arg);
971        return 0;
972}
973
974static int read_get_rate(MSFilter * f, void *arg)
975{
976        AQData *d = (AQData *) f->data;
977        *((int *) arg) = d->rate;
978        return 0;
979}
980
981static int write_get_rate(MSFilter * f, void *arg)
982{
983        AQData *d = (AQData *) f->data;
984        *((int *) arg) = d->rate;
985        return 0;
986}
987
988/*
989static int set_nchannels(MSFilter *f, void *arg){
990        AQData *d=(AQData*)f->data;
991        d->stereo=(*((int*)arg)==2);
992        return 0;
993}
994*/
995
996static MSFilterMethod aq_read_methods[] = {
997        {MS_FILTER_SET_SAMPLE_RATE, set_rate},
998        {MS_FILTER_GET_SAMPLE_RATE, read_get_rate},
999/* not support yet
1000        {       MS_FILTER_SET_NCHANNELS         , set_nchannels },
1001*/
1002        {0, NULL}
1003};
1004
1005MSFilterDesc aq_read_desc = {
1006        .id = MS_AQ_READ_ID,
1007        .name = "MSAQRead",
1008        .text = N_("Sound capture filter for MacOS X Audio Queue Service"),
1009        .category = MS_FILTER_OTHER,
1010        .ninputs = 0,
1011        .noutputs = 1,
1012        .init = aq_init,
1013        .preprocess = aq_read_preprocess,
1014        .process = aq_read_process,
1015        .postprocess = aq_read_postprocess,
1016        .uninit = aq_uninit,
1017        .methods = aq_read_methods
1018};
1019
1020static MSFilterMethod aq_write_methods[] = {
1021        {MS_FILTER_SET_SAMPLE_RATE, set_rate},
1022        {MS_FILTER_GET_SAMPLE_RATE, write_get_rate},
1023/* not support yet
1024        {       MS_FILTER_SET_NCHANNELS         , set_nchannels },
1025*/
1026        {0, NULL}
1027};
1028
1029MSFilterDesc aq_write_desc = {
1030        .id = MS_AQ_WRITE_ID,
1031        .name = "MSAQWrite",
1032        .text = N_("Sound playback filter for MacOS X Audio Queue Service"),
1033        .category = MS_FILTER_OTHER,
1034        .ninputs = 1,
1035        .noutputs = 0,
1036        .init = aq_init,
1037        .preprocess = aq_write_preprocess,
1038        .process = aq_write_process,
1039        .postprocess = aq_write_postprocess,
1040        .uninit = aq_uninit,
1041        .methods = aq_write_methods
1042};
1043
1044MSFilter *ms_aq_read_new(MSSndCard * card)
1045{
1046        MSFilter *f = ms_filter_new_from_desc(&aq_read_desc);
1047        AqSndDsCard *wc = (AqSndDsCard *) card->data;
1048        AQData *d = (AQData *) f->data;
1049        d->uidname = NULL;
1050        if (wc->uidname != NULL)
1051                d->uidname = CFStringCreateCopy(NULL, wc->uidname);
1052        memcpy(&d->devicereadFormat, &wc->devicereadFormat,
1053                   sizeof(AudioStreamBasicDescription));
1054        memcpy(&d->devicewriteFormat, &wc->devicewriteFormat,
1055                   sizeof(AudioStreamBasicDescription));
1056        return f;
1057}
1058
1059
1060MSFilter *ms_aq_write_new(MSSndCard * card)
1061{
1062        MSFilter *f = ms_filter_new_from_desc(&aq_write_desc);
1063        AqSndDsCard *wc = (AqSndDsCard *) card->data;
1064        AQData *d = (AQData *) f->data;
1065        d->uidname = NULL;
1066        if (wc->uidname != NULL)
1067                d->uidname = CFStringCreateCopy(NULL, wc->uidname);
1068        memcpy(&d->devicereadFormat, &wc->devicereadFormat,
1069                   sizeof(AudioStreamBasicDescription));
1070        memcpy(&d->devicewriteFormat, &wc->devicewriteFormat,
1071                   sizeof(AudioStreamBasicDescription));
1072        return f;
1073}
1074
1075MS_FILTER_DESC_EXPORT(aq_read_desc)
1076MS_FILTER_DESC_EXPORT(aq_write_desc)
Note: See TracBrowser for help on using the repository browser.