/* * 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; }