How to manually convert 8.24-bit lpcm deinterleaving to 16-bit lpcm?

I have a piece of data (void *), which is 2 ch, 44100 Hz, the 'lpcm' is an 8.24 bit character with a string de-relocated. I need to write this fragment to a file as 2 ch, 44100 Hz, lpcm '16 bit signed low-value integer.

How do i convert data? I can imagine that I need to do something like this:

uint dataByteSize = sizeof(UInt32) * samplesCount; UInt32* source = ...; UInt32* dest = (UInt32*)malloc(dataByteSize); for (int i = 0; i < samplesCount; ++i) { UInt32 sourceSample = source[i]; UInt32 destSample = sourceSample>>24; dest[i] = destSample; } 

But how to convert converts to alternation?

+6
core audio
source share
4 answers

Well, I spent some time studying the problem and realized that this question contains too little information to answer =) Thus, the deal is concluded:

Firstly, about the unmoved ones: At first I thought that it would look like this: l1 l2 l3 l4 ... ln r1 r2 r3 r4 ... rn But it turned out that the right channel was simply absent in my data. It turned out that this is not non-moving data, it is just simple monophonic data. And yes, it should always be multiple buffers if the data is not actually interleaved. If it alternates, it should be l1 r1 l2 r2 l3 r3 l4 r4 ...

Secondly, about the actual transformation: it all depends on the range of samples. In my case (and in any case, when the main sound is activated, if I'm right), fixed-point 8.24 values ​​should be in the range between (-1, 1), and 16-bit signed values ​​should be in the range between (-32768 , 32767). Thus, a value of 8.24 will always have the first 8 bits, either 0 (in the case of a positive) or 1 (in the case of a negative value). These first 8 bits must be removed (keeping the c sign). In addition, you can remove as many bits as you want - it will simply reduce the sound quality, but it will not ruin the sound. In the case of conversion to 16-bit format, bit 8-22 (15 bits) will actually contain the data that we must use for SInt16. Bit 7 can be used as a sign bit. Therefore, to convert 8.24 to SInt16, you just need to shift 9 bits to the right (9, because you need to keep the character) and transfer to SInt16

11111111 10110110 11101110 10000011 β†’ 11111111 11111111 (11011011 01110111)
00000000 01101111 00000000 11000001 β†’ 00000000 00000000 (00110111 10000000)

What is it. Nothing more than repeating through an array and shifting bits to the right. I hope that he will save someone a couple of hours.

+11
source share

I read the next clip in audiography https://github.com/tkzic/audiograph

 /* convert sample vector from fixed point 8.24 to SInt16 */ void fixedPointToSInt16( SInt32 * source, SInt16 * target, int length ) { int i; for(i = 0;i < length; i++ ) { target[i] = (SInt16) (source[i] >> 9); } } 
+3
source share

A better description can be found at http://lists.apple.com/archives/coreaudio-api/2011/Feb/msg00083.html

So,

8.24 numbers are interpreted as from -128.000000000000 to +127.999999940393

But!

The agreement in iOS / CoreAudio should process from -1.000000000000 to +0.999969482421875 as uncut values ​​that do not exceed Full Scale for 16-bit analog audio converters.

Ok

0
source share

I tried a popular method with a 9-bit shift, and for some reason it does not work for me, since I also use the result for encoding in ogg. The led ogg was noisy. What kind of work it is, this function is based on the method that I found in audiography https://github.com/tkzic/audiograph

 void ConvertInputToInt16(AudioStreamBasicDescription inFormat, void *buf, void *outputBuf, size_t capacity) { AudioConverterRef converter; OSStatus err; size_t bytesPerSample = sizeof(SInt16); AudioStreamBasicDescription outFormat = {0}; outFormat.mFormatID = kAudioFormatLinearPCM; outFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; outFormat.mBitsPerChannel = 8 * bytesPerSample; outFormat.mFramesPerPacket = 1; outFormat.mChannelsPerFrame = 1; outFormat.mBytesPerPacket = bytesPerSample * outFormat.mFramesPerPacket; outFormat.mBytesPerFrame = bytesPerSample * outFormat.mChannelsPerFrame; outFormat.mSampleRate = inFormat.mSampleRate; NSLog(@"description for in format: %@", descriptionForAudioFormat(inFormat)); NSLog(@"description for out format: %@", descriptionForAudioFormat(outFormat)); UInt32 inSize = capacity*sizeof(SInt32); UInt32 outSize = capacity*sizeof(SInt16); // this is the famed audio converter err = AudioConverterNew(&inFormat, &outFormat, &converter); if(noErr != err) { NSLog(@"error in audioConverterNew: %d", (int)err); } err = AudioConverterConvertBuffer(converter, inSize, buf, &outSize, outputBuf); if(noErr != err) { NSLog(@"error in audioConverterConvertBuffer: %d", err); } } 
0
source share

All Articles