Advertise here




Advertise here

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

AudioStreamBasicDescription Headache

Hero1000Hero1000 Posts: 40Registered Users
edited June 2010 in iPhone SDK Development
Hi,

I'm trying to record some 8 bit audio but I keeping getting 'format' error or error -50 (don't know what that is). For the life of me I can't work out whats wrong, anyone got any ideas?
format->mSampleRate = 22000.0;
	format->mFormatID = kAudioFormatLinearPCM;
	format->mFramesPerPacket = 1;
	format->mChannelsPerFrame = 1;
	format->mBytesPerFrame = 1;
	format->mBytesPerPacket = 1;
	format->mBitsPerChannel = 8;
	format->mReserved = 0;
	format->mFormatFlags = kLinearPCMFormatFlagIsBigEndian |
	kLinearPCMFormatFlagIsSignedInteger |
	kLinearPCMFormatFlagIsPacked;

I know it's something in the format because if I use the following code it all works fine.
format->mSampleRate = 8000.0;
	format->mFormatID = kAudioFormatLinearPCM;
	format->mFramesPerPacket = 1;
	format->mChannelsPerFrame = 1;
	format->mBytesPerFrame = 2;
	format->mBytesPerPacket = 2;
	format->mBitsPerChannel = 16;
	format->mReserved = 0;
	format->mFormatFlags = kLinearPCMFormatFlagIsBigEndian |
		kLinearPCMFormatFlagIsSignedInteger |
		kLinearPCMFormatFlagIsPacked;

Many many thanks in advance!
Post edited by Hero1000 on

Replies

  • RLScottRLScott Posts: 1,652Tutorial Authors, Registered Users @ @ @ @
    edited June 2009
    Let the audio stream capture the audio in 16-bit format, and then you convert it to 8-bit format as part of your processing and recording.

    Robert Scott
    Ypsilanti, Michigan
  • Hero1000Hero1000 Posts: 40Registered Users
    edited June 2009
    RLScott wrote: »
    Let the audio stream capture the audio in 16-bit format, and then you convert it to 8-bit format as part of your processing and recording.

    Robert Scott
    Ypsilanti, Michigan

    I was afraid someone was going to say that - I have no real understanding of audio processing, all I need to do is fill an array with 8 bit raw audio data and then I'm done - but everything seems to get in my way!!

    Whats the easiest way to convert it?

    Thanks in advance
  • RLScottRLScott Posts: 1,652Tutorial Authors, Registered Users @ @ @ @
    edited June 2009
    Hero1000 wrote: »
    ...all I need to do is fill an array with 8 bit raw audio data ...Whats the easiest way to convert it?
    The data you will be getting from the audio stream is an array of signed short int (16 bit). By converting it to 8-bit you will be losing lots of resolution, but if that's unavoidable when you only have 8 bits in which to store a sample. I suppose you could take the high-order 8-bits of each sample, something like this:
      signed short int *audioBuffer;   //..points into the buffer provided by audio callback
      signed char *myBuffer;  //..points into your buffer of 8-bit samples
    
      *myBuffer = (*audioBuffer)>>8;
       myBuffer++;   audioBuffer++;
    
    This is, of course, part of a loop that transfers each sample. It is important aht audioBuffer be declared a pointer to a signed quantity so that the right shift (>>8) will be an arithmetic and not a logical shift.

    Robert Scott
    Ypsilanti, Michigan
  • Hero1000Hero1000 Posts: 40Registered Users
    edited June 2009
    RLScott wrote: »
    The data you will be getting from the audio stream is an array of signed short int (16 bit). By converting it to 8-bit you will be losing lots of resolution, but if that's unavoidable when you only have 8 bits in which to store a sample. I suppose you could take the high-order 8-bits of each sample, something like this:
      signed short int *audioBuffer;   //..points into the buffer provided by audio callback
      signed char *myBuffer;  //..points into your buffer of 8-bit samples
    
      *myBuffer = (*audioBuffer)>>8;
       myBuffer++;   audioBuffer++;
    
    This is, of course, part of a loop that transfers each sample. It is important aht audioBuffer be declared a pointer to a signed quantity so that the right shift (>>8) will be an arithmetic and not a logical shift.

    Robert Scott
    Ypsilanti, Michigan

    Thank you so much Robert! You are a star!

    But to show what a noob and complete lack of understanding I have about this, how do you loop through all the samples?

    Many thanks again
  • zhylazhyla Posts: 253Registered Users
    edited June 2009
    Ummm... no, lopping off 8 bits of a 16 bit sample isn't the same as recording 8 bit samples. You'll be decreasing the volume by half and likely losing all of your sound. You'd want to dither to 8 bits... I don't really know how to do that off the top of my head.

    The real question is why you think you need 8-bit audio. Why not just record 16-bit audio?
  • Hero1000Hero1000 Posts: 40Registered Users
    edited June 2009
    zhyla wrote: »
    The real question is why you think you need 8-bit audio. Why not just record 16-bit audio?

    I need 8 bit because the C code I'm running through expects 8 bit unfortunatly.

    So am I right in thinking that the iphone can't record natively 8 bit audio?

    Looks like there maybe an audio converter in the SDK, will try it tonight.

    Thanks
  • RLScottRLScott Posts: 1,652Tutorial Authors, Registered Users @ @ @ @
    edited June 2009
    zhyla wrote: »
    Ummm... no, lopping off 8 bits of a 16 bit sample isn't the same as recording 8 bit samples. You'll be decreasing the volume by half and likely losing all of your sound...
    Not true. The volume with be exactly the same. If the 16-bit data had a range of 30% of full scale, then that means it ranges from -9830 to +9830. After lopping of the lower-order 8 bits, this range becomes -38 to +38, which is still 30% of the full-scale range of -128 to +127. What you lose is resolution.

    Here is how one would loop through all the samples in a callback function:
    void listener_callback(void *userData,
        AudioQueueRef inQ,
        AudioQueueBufferRef inBuf,
        const AudioTimeStamp *inStartTime,
        UInt32 inNumberPacketDescriptions,
        const AudioStreamPacketDescription *inPacketDesc)
    { //....With 1024 samples per audio buffer, this callback gets called 21.53 times per second
    
        short int *ibuf = (short*)inBuf->mAudioData;
        for(int i=0; i<1024; i++)
        {
            my8BitBuffer[i] = ibuf[i]>>8;
        }
        AudioQueueEnqueueBuffer(inQ, inBuf, 0, NULL);
    
    }
    
  • zhylazhyla Posts: 253Registered Users
    edited June 2009
    Eh, you're right. It seems wrong to me but I worked out the math and yes, right shift by 8 and it's just as good as recording 8 bit. Sorry for my misinformation.
  • Hero1000Hero1000 Posts: 40Registered Users
    edited June 2009
    Robert,

    Thank you so much that works a treat!
  • amitchauhanamitchauhan Posts: 28Registered Users @
    edited June 2010
    Hero1000 wrote: »
    Robert,

    Thank you so much that works a treat!

    I required a recording in 8 bit.means i have a same requirement.
    While as you suggest in your thread. We will have record in 16 bit and then convert it to 8 bit.

    Can you please help me to sort out this issue.

    My line of of code is here.
    I have change the sample rate etc acordingly.

    static void recordingCallback (
    void *inUserData,
    AudioQueueRef inAudioQueue,
    AudioQueueBufferRef inBuffer,
    const AudioTimeStamp *inStartTime,
    UInt32 inNumPackets,
    const AudioStreamPacketDescription *inPacketDesc
    ) {
    // This callback, being outside the implementation block, needs a reference to the AudioRecorder object
    VNotesRecorder *recorder = (VNotesRecorder *) inUserData;

    // if there is audio data, write it to the file
    if (inNumPackets > 0) {

    AudioFileWritePackets (
    [recorder audioFileID],
    FALSE,
    inBuffer->mAudioDataByteSize,
    inPacketDesc,
    recorder.startingPacketNumber,
    &inNumPackets,
    inBuffer->mAudioData
    );

    [recorder incrementStartingPacketNumberBy: (UInt32) inNumPackets];
    }

    // if not stopping, re-enqueue the buffer so that it can be filled again
    if ([recorder isRunning]) {

    AudioQueueEnqueueBuffer (
    inAudioQueue,
    inBuffer,
    0,
    NULL
    );
    }
    }

    I would like to send an email to amitkushvaha@gmail.com

    I will be appreciated for your help.

    Thanks in Advance.
Sign In or Register to comment.