On 2008-02-25 14:10, Eric Blossom wrote: > The code doesn't support S24_3LE because when we wrote it, we didn't > have any cards that used that format, and it wasn't obvious (to me) > exactly how the format was represented. It would be great if you > could sort this out and submit a patch with the fix.
Alright, I sort of got it to work, I'm at least pretty sure about the format of S24_3LE. I attached the code (just the work_s24_2x1 function with lots of comments) to this email, if you want to take a look. There might be a better way to do this, but so far I couldn't think of anything. I'm still having a problem with it though and I need help to sort it out. Most of the time I get buffer overruns from audio_alsa_source::read_buffer(). The function I wrote seems to work, this morning I got a clean signal from my sound card (24-bit, 96kHz), but when I ran the same code later (after some experiments) it produced buffer overruns again. Alsa reference [1] says: > The overrun can happen when an application does not take new captured > samples in time from alsa-lib. Is it a speed-issue, is some buffer too small? What am I doing wrong? Thank you! Matt [1] http://howto.gp.mines.edu/local-apps/alsa-lib-devel-1.0.14/doxygen/html/pcm.html#pcm_errors -- Mathis Richter <[EMAIL PROTECTED]> GnuPG Fingerprint: 5069 3C27 0178 D542 DFB4 04F6 29BD 9EF2 1BE0 DDF6
/* * Work function that deals with float to S24 conversion */ int audio_alsa_source::work_s24_2x1 (int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { typedef gr_int32 sample_t; // the type of samples we're creating static const int NBITS = 24; // # of bits in a sample unsigned int nchan = output_items.size (); float **out = (float **) &output_items[0]; unsigned char *buf = (unsigned char *) d_buffer; assert(nchan == 1); int bi; // actually using 24 bits instead of 32 unsigned int sizeof_frame = d_hw_nchan * (sizeof (sample_t) - 1); assert (d_buffer_size_bytes == d_period_size * sizeof_frame); // To minimize latency, return at most a single period's worth of samples. // [We could also read the first one in a blocking mode and subsequent // ones in non-blocking mode, but we'll leave that for later (or never).] if (!read_buffer (buf, d_period_size, sizeof_frame)) return -1; // No fixing this problem. Say we're done. // process one period of data // // // Every frame will have the following byte format: // // [ byte1_L | byte2_L | byte3_L | byte1_R | byte2_R | byte3_R ] // // while byte1 will contain the least significant bits of the 24-bit // integer, so the bytes will have to be reassembled in reverse order. // Three subsequent bytes represent the 24-bit integer for a channel, the // following three bytes will contain the sample of the next channel. // // The bit that determins the sign of the integer will be the 8th bit from // the right in byte3. It will later have to be moved to the 32nd bit // in the final integer. // bi = 0; for (unsigned int i = 0; i < d_period_size; i++) { int t[nchan]; for (unsigned int chan = 0; chan < 2; chan++) { // get first byte from buffer and put it into a 32-bit integer // t's bytes will look like this: // t = [ empty | empty | empty | byte1 ] t[chan] = (buf[bi++]); // shift the next byte 1 byte to the left so that t's bytes look like this: // t = [ empty | empty | byte2 | byte1 ] t[chan] = t[chan] | (buf[bi++] << 8); // shift the next byte 2 bytes to the left // t = [empty | byte3 | byte2 | byte1 ] t[chan] = t[chan] | (buf[bi++] << 16); // sign of the integer is at the 24th bit (from the right) // shift it to the 32nd bit (from the right) int sign = (t[chan] & (1 << 23)) << 8; int value; // if the integer we received is negativ // t OR (0111 1111 1000 0000 0000 0000 0000 0000) // so that all bits that were still 0 are switched to 1 if (sign != 0) value = (t[chan] | 0x7f800000); // if the integer is positive, retain all bit values, but make sure // that the one where the 'sign' bit used to be is 0 // t AND (1111 1111 0111 1111 1111 1111 1111 1111) else value = (t[chan] & 0xff7fffff); // combine the value of the integer with its sign t[chan] = sign | value; } int a = (t[0] + t[1]) / 2; out[0][i] = (float) a * (1.0 / (float) ((1L << (NBITS-1)) - 1)); } return d_period_size; }
signature.asc
Description: Digital signature
_______________________________________________ Discuss-gnuradio mailing list Discuss-gnuradio@gnu.org http://lists.gnu.org/mailman/listinfo/discuss-gnuradio