[Speex-dev] Speexdec says: 'This doesn't look like a Speex file' (am I missing headers?)

Mikhail Dudarev mikejd at mihteh.com
Tue Feb 12 06:28:06 PST 2013


Hello, guys!

I'm a novice at programming, learning about the speex and its applications
now. Specifically, my current goal is to encode microphone input on iOS
device in real-time, saving result to a file frame-by-frame.

So far, I've managed to:

1) compile speex static library (it works, at least for iPhone/iPad, but
not on iOS simulator; this is fine for now);
2) encode pcm data from microphone into 'something' which resembles speex
(in fact it expected to be speex file, but not actually; see below for
details).

To check validity of the result file, I use speexdec script, as following:

    ...$ speexdec encodingResultSpeexFile decodedSpeexFile
    This doesn't look like a Speex file

So I assume that the file, which my program creates, is invalid for some
reason. Is some particular kind of header required? What should it be (ogg,
rtp or something else) and how should I add it?

Could you guide me in right direction, please?

---

To give you fuller picture, I'll attach single audio input buffer along
with piece of the code to encode bytes from such buffers frame-by-frame:

a) Audio input buffer (abridged a bit):

    CMSampleBuffer 0x6ead20 retainCount: 1 allocator: 0x33bdf213
    invalid = NO
    ...
    formatDescription = <CMAudioFormatDescription 0x6e84b0 [0x3f7cd650]> {
        mediaType:'soun'
        mediaSubType:'lpcm'
        mediaSpecific: {
            ASBD: {
                mSampleRate: 44100.000000
                mFormatID: 'lpcm'
                mFormatFlags: 0xc
                mBytesPerPacket: 2
                mFramesPerPacket: 1
                mBytesPerFrame: 2
                mChannelsPerFrame: 1
                mBitsPerChannel: 16
            } ...
        }  ...
    }
    sbufToTrackReadiness = 0x0
    numSamples = 375
    sampleTimingArray[1] = {
        {PTS = {82626949766094/1000000000 = 82626.950, rounded}, DTS =
{INVALID}, duration = {1/44100 = 0.000}},
    }
    sampleSizeArray[1] = {
        sampleSize = 2,
    }
    dataBuffer = 0x6e7a40


b) Actual data which is kept in aforementioned buffer (for the sake of
completeness):

0f001400 0b000d00 04000a00 f7ff1300 0a000300 f9ff1c00 1b001c00 f9ffc0ff
bfffadff b7ff86ff 7cff5fff 63ff67ff 84ffb5ff bbffd4ff e4ff1500 1c001000
04001400 39002500 27005000 44002000 e7ffe5ff c7ffd7ff bbffcbff d1ffc8ff
c7ffc4ff e8fff6ff 2f003a00 5c005400 66006600 71006700 5e006000 4a003300
0a002300 4a004c00 47001c00 fbfff6ff 0a00b1ff 8dff85ff 9bff87ff 93ff7fff
84ff74ff 6fff75ff 91ffa2ff c1ff9aff 86ff7eff 7aff59ff 53ff6aff 71ffb3ff
c5ffe1ff 0900faff e9fff3ff 1d003100 34001400 0600fcff d5ffecff 0d002200
60006500 6f006c00 61002b00 0700d8ff ccffcbff baff7aff 65ff61ff 94ffccff
0e002800 56006400 9800ad00 ea00c700 cb00ab00 af00bc00 ab00be00 a700ad00
76006d00 34003100 0c00e7ff c2ffcbff c6ffcdff acffadff a2ff88ff 86ff4aff
5eff19ff 3eff26ff 66ff8bff bcffe9ff d8ff3300 1e006a00 7600a700 7e009f00
b2000801 15011501 d100d900 92008f00 86007b00 62004900 6d006e00 52002f00
f0ff0000 b6ffebff 96ffb0ff 51ff76ff 45ff61ff 18ff2aff 12ff29ff 2fff70ff
6aff9fff b6ffdeff c3ffd9ff a8ffc0ff b7fffbff 00001e00 c4ffe4ff dbffe1ff
d5ff0300 0e001c00 03000800 0b001f00 d9ff1a00 d7ffe3ff bdff0300 f6ff1b00
c9ffecff 06005e00 50009100 60005f00 05002000 ffff1200 dfffecff d9ff0100
ccfff3ff b2ffceff 9bffd4ff c5ffe2ff b1ffecff e0ff0000 e6fffbff e2ff1c00
11002a00 11003900 4c009800 8a00b100 63008800 66008d00 65008600 69006700
5e006200 74006f00 5f006700 62006700 4f007100 75007800 7a006f00 65005200
1f00d7ff caffb8ff aaffb4ff 9aff6eff 61ff6bff 5dff6cff 75ff75ff 77ff95ff
adffd3ff d9ffd7ff f6ff0700 1a002f00 40001e00 1b000e00 1a001400 25002800
38002900 1d002000 0000e6ff effff2ff 0100dbff daffb9ff efffe6ff e4ffd5ff
dbffb5ff 89ff8dff a6ffc1ff e3ffd5ff f7ff0500 0e00e9ff 0f001200 2f002c00
37004e00 46002500 d3ffbbff b0ff

c) The code (here is the piece to deal with single input buffer, which
example is give above; so it's same for all input buffers):

    int writtenBytesNumber;
    SpeexBits bits;
    int samplesPerFrame;
    int quality = 6;
    char compressedBits[200];

    speex_bits_init(&bits);
    memset(compressedBits, 0, 200);

    void *encoderState = speex_encoder_init(&speex_wb_mode); // setting
wideband mode
    speex_encoder_ctl(encoderState, SPEEX_GET_FRAME_SIZE,
&samplesPerFrame); // 320 samples/frame

    speex_encoder_ctl(encoderState, SPEEX_SET_QUALITY, &quality);

    CMItemCount numberOfSamples =
CMSampleBufferGetNumSamples(sampleBuffer); // 375 samples
    size_t sampleSize = CMSampleBufferGetSampleSize(sampleBuffer, 0); // 2
bytes

    CMBlockBufferRef blockBufferRef =
CMSampleBufferGetDataBuffer(sampleBuffer); // see attachment (b) above
    size_t blockBufferDataLength =
CMBlockBufferGetDataLength(blockBufferRef); // 750 bytes

    NSMutableData *allSamplesMutableData = [NSMutableData
dataWithLength:blockBufferDataLength];
    CMBlockBufferCopyDataBytes(blockBufferRef, 0, blockBufferDataLength,
allSamplesMutableData.mutableBytes); // copying bytes to object

    int nextSampleStartPosition = 0;

    for (int i = 0; i < numberOfSamples; i++) {

        NSData *singleSampleData = [NSData
dataWithBytes:[[allSamplesMutableData subdataWithRange:NSMakeRange(
nextSampleStartPosition, sampleSize)] bytes] length:sampleSize];

        nextSampleStartPosition += sampleSize;
        [_intermediateSampleBuffer addObject:singleSampleData]; // we put
samples here until it's enough for the frame

        if (_intermediateSampleBuffer.count == samplesPerFrame) {

            speex_bits_reset(&bits);
            short samplesArray[samplesPerFrame]; // c-array which will get
samples from _intermediateSampleBuffer

            for (int j = 0; j < samplesPerFrame; j++) {
                samplesArray[j] = (short)[(NSData
*)[_intermediateSampleBuffer objectAtIndex:j] bytes];
            }

            [_intermediateSampleBuffer removeAllObjects]; // flushing
_intermediateSampleBuffer
to make it ready for next samples

            speex_encode_int(encoderState, samplesArray, &bits);
            writtenBytesNumber = speex_bits_write(&bits, compressedBits,
samplesPerFrame); // usually 52 bytes for wideband and quality=6

            fwrite(&writtenBytesNumber, sizeof(int), 1, _speexFile); //
following the example in sampleenc.c we put size of compressedBits first
            fwrite(compressedBits, sizeof(char), writtenBytesNumber,
_speexFile); // putting encoded bits themselves

            memset(compressedBits, 0, 200);
        }
    }

    speex_bits_destroy(&bits);
    speex_encoder_destroy(encoderState);

p.s. I understand that code is far from optimal, but it's not final
version. Though advice regarding code (if any) quality is also appreciated.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.xiph.org/pipermail/speex-dev/attachments/20130212/9327e353/attachment.htm 


More information about the Speex-dev mailing list