• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: A simple 'Device Through' app (need some help).
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: A simple 'Device Through' app (need some help).


  • Subject: Re: A simple 'Device Through' app (need some help).
  • From: "Glenn McCord" <email@hidden>
  • Date: Thu, 10 Jul 2008 08:26:07 +1200

It looks like I finally have something that works. I made a better
queue and made sure it gets filled a little bit first (with silence)
to ensure that the audio callback always has something to process. I
do get some pops initially but then it comes right, at least a heck of
a lot more 'right' than what I was getting before. There is the odd
blemish every so often but I'll blame that on bad drivers.

For the sake of anyone else who is curious, I have posted some of the
relevant code below. I had to cut bits out because the moderators
rejected it the first time I sent it.

Once again, thanks for all the help and hopefully I needn't pursue
this small adventure further. Regardless, if someone wants to critique
the following code, then be my guest.

Glenn


*** snip ***

class AudioDataQueue
{
public:
       AudioDataQueue() : mMaxSize(100), mWriteIndex(0), mReadIndex(0), mSize(0)
       {
               mDataByteSize = FRAME_SIZE * NUM_CHANNELS * sizeof(float);

               mQueue = (Byte**)malloc(mMaxSize * sizeof(Byte*));
               for (int i=0; i<mMaxSize; i++)
               {
                       mQueue[i] = (Byte*)malloc(mDataByteSize);
               }

       };

       virtual ~AudioDataQueue(){ };

       void Queue(Byte *data)
       {
               memcpy(mQueue[mWriteIndex++], data, mDataByteSize);

               if (mWriteIndex >= mMaxSize) mWriteIndex = 0;
               mSize++;
       };

       void Dequeue(void *data)
       {
               //fill an AudioBuffer with bytes
               memcpy(data, mQueue[mReadIndex++], mDataByteSize);

               if (mReadIndex >= mMaxSize) mReadIndex = 0;
               mSize--;
       };

       int Size() { return mSize };

public:

       Byte **mQueue;
       int mWriteIndex;
       int mReadIndex;
       int mSize;
       int mDataByteSize;
       int mMaxSize;
};

*** snip ***



// This is not for input-only streams, this is for streams where the
input device is different from the output device
OSStatus AudioInputProc( AudioDeviceID inDevice,
                        const AudioTimeStamp* inNow,
                        const AudioBufferList* inInputData,
                        const AudioTimeStamp* inInputTime,
                        AudioBufferList* outOutputData,
                        const AudioTimeStamp* inOutputTime,
                        void* inClientData)
{


       if (state == 1) {
               printf("%d: %d : The output hasn't been called yet\n",
++errorCount, adq.mSize);
       }
       state = 1;

       adq.Queue( (Byte*)(inInputData->mBuffers[0].mData) );


   return noErr;

}

// This is not for output-only streams, this is for streams where the
input device is different from the output device
OSStatus AudioOutputProc( AudioDeviceID inDevice,
                         const AudioTimeStamp* inNow,
                         const AudioBufferList* inInputData,
                         const AudioTimeStamp* inInputTime,
                         AudioBufferList* outOutputData,
                         const AudioTimeStamp* inOutputTime,
                         void* inClientData)
{
       if (adq.Size() < 5)
       {
               //play some silence
               memset(outOutputData->mBuffers[0].mData, 0, FRAME_SIZE
* NUM_CHANNELS * sizeof(float));
       }

       if (state == 2) {
               printf("%d: %d : The input hasn't been called yet\n",
--errorCount, adq.mSize);
       }
       state = 2;

       adq.Dequeue( outOutputData->mBuffers[0].mData );

   return noErr;
}



On Wed, Jul 9, 2008 at 10:12 AM, Mikael Hakman <email@hidden> wrote:
> On July 04, 2008 5:41 AM, Glenn McCord wrote:
>>
>> Just to bring this thread full circle again, I was able to make a
>> console 'through' application by looking at the Portaudio source code.
>> They used to use a HAL implementation which is coded inside
>> pa_mac_core_old.cpp.
>>
>> With the help of that code and some other sources, I was able to make
>> a console application that plays through the inputs and straight to
>> the outputs. Unfortunately I get very regular, almost rhythmic popping
>> (imperfections in the audio) with frame sizes up to 2056 (I haven't
>> tried higher). This is despite being able to use Portaudio with a
>> frame size of 64 with no audio imperfections.
>>
>> As much as I don't want to, I have attached the code to this email
>> with the hope that something really really obvious is causing the
>> problems.
>> Essentially I'm using the following code flow
>> - Find the input and output ids of my device
>> - set the sample rates and frame buffer size for the device
>> - set up and input and output callback
>> - make a temporary AudioBufferList object to store the input data so
>> that it can be copied to the output
>>
>> Then the callbacks do their thing and data gets copied from input to
>> output.
>>
>> One of the guys suggested that Portaudio does some kind of extra
>> buffering, but that would have to be some significant buffering.
>>
>> Just a couple of points:
>> - My device is regarded as two devices, input and output.
>> - If I create a sine wave programatically and copy that data straight
>> to output, then I get no imperfections in playback.
>>
>> Hopefully my issue is relatively simple, but I've been at this all
>> week and need a bit of help.
>
> Here is good news. After reading through the thread "Programmatic Aggregate
> Device issue on Intel Mac" I decided to try to create an Aggregate Device
> out of my built-in input and output devices, not programmatically but using
> SAM panel. I did it once before and it didn't work - as soon as I checked
> input or output device, the other one was not selectable anymore. This time
> however it worked - now I have one device consisting of both input and
> output. I didn't actually play anything through it but HALLab shows clearly
> both its input and output sides. Perhaps it was fixed in the newest OS
> update. If you can do the same for your USB device then you could forget all
> about buffering and queues and use the aggregate device instead of separate
> input and output devices and have input delivered in the same IOProc and
> simultaneously with output.
>
> Regards/Mikael
>
>
>
 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:

This email sent to email@hidden

References: 
 >Re: A simple 'Device Through' app (need some help). (From: "Mikael Hakman" <email@hidden>)

  • Prev by Date: Re: Programmatic Aggregate Device issue on Intel Mac, not always completing initialisation?
  • Next by Date: Re: Programmatic Aggregate Device issue on Intel Mac, not always completing initialisation?
  • Previous by thread: Re: A simple 'Device Through' app (need some help).
  • Next by thread: Re: Stopping actions mid stream
  • Index(es):
    • Date
    • Thread