Вопрос

I am currently in the process of building an application that reads in audio from my iPhone's microphone, and then does some processing and visuals. Of course I am starting with the audio stuff first, but am having one minor problem.

I am defining my sampling rate to be 44100 Hz and defining my buffer to hold 4096 samples. Which is does. However, when I print this data out, copy it into MATLAB to double check accuracy, the sample rate I have to use is half of my iPhone defined rate, or 22050 Hz, for it to be correct.

I think it has something to do with the following code and how it is putting 2 bytes per packet, and when I am looping through the buffer, the buffer is spitting out the whole packet, which my code assumes is a single number. So what I am wondering is how to split up those packets and read them as individual numbers.

- (void)setupAudioFormat {
    memset(&dataFormat, 0, sizeof(dataFormat));
    dataFormat.mSampleRate = kSampleRate;
    dataFormat.mFormatID = kAudioFormatLinearPCM;
    dataFormat.mFramesPerPacket = 1;
    dataFormat.mChannelsPerFrame = 1;
    //  dataFormat.mBytesPerFrame = 2;
    //  dataFormat.mBytesPerPacket = 2;
    dataFormat.mBitsPerChannel = 16;
    dataFormat.mReserved = 0;

    dataFormat.mBytesPerPacket = dataFormat.mBytesPerFrame = (dataFormat.mBitsPerChannel / 8) * dataFormat.mChannelsPerFrame;
    dataFormat.mFormatFlags = 
    kLinearPCMFormatFlagIsSignedInteger |
    kLinearPCMFormatFlagIsPacked;
}

If what I described is unclear, please let me know. Thanks!

EDIT

Adding the code that I used to print the data

float *audioFloat =  (float *)malloc(numBytes * sizeof(float));
int *temp = (int*)inBuffer->mAudioData;
int i;
float power = pow(2, 31);
for (i = 0;i<numBytes;i++) {
    audioFloat[i] = temp[i]/power;
    printf("%f ",audioFloat[i]);
}
Это было полезно?

Решение

I found the problem with what I was doing. It was a c pointer issue, and since I have never really programmed in C before, I of course got them wrong.

You can not directly cast inBuffer->mAudioData to an int array. So what I simply did was the following

SInt16 *buffer = malloc(sizeof(SInt16)*kBufferByteSize);
buffer = inBuffer->mAudioData;

This worked out just fine and now my data is of correct length and the data is represented properly.

Другие советы

I saw your answer, there also is an underlying issue which gives wrong sample data bytes which is because of an endian issue of bytes being swapped.

-(void)feedSamplesToEngine:(UInt32)audioDataBytesCapacity audioData:(void *)audioData { int sampleCount = audioDataBytesCapacity / sizeof(SAMPLE_TYPE);

SAMPLE_TYPE *samples = (SAMPLE_TYPE*)audioData;
//SAMPLE_TYPE *sample_le = (SAMPLE_TYPE *)malloc(sizeof(SAMPLE_TYPE)*sampleCount );//for swapping endians

std::string shorts;
double power = pow(2,10);
for(int i = 0; i < sampleCount; i++)
{
    SAMPLE_TYPE sample_le =  (0xff00 & (samples[i] << 8)) | (0x00ff & (samples[i] >> 8)) ; //Endianess issue
    char dataInterim[30];
    sprintf(dataInterim,"%f ", sample_le/power); // normalize it.
    shorts.append(dataInterim);
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top