summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrank Gevaerts <frank@gevaerts.be>2008-04-01 20:36:51 +0000
committerFrank Gevaerts <frank@gevaerts.be>2008-04-01 20:36:51 +0000
commit688f8decf4c1b360bdd1a5ff91cf007eca4d52f9 (patch)
treeb98a38a3fc1569531e2a0995558c8f8afea6bad9
parent92717eb9ed97447e725fb3ac6cb3182589053366 (diff)
downloadrockbox-688f8decf4c1b360bdd1a5ff91cf007eca4d52f9.zip
rockbox-688f8decf4c1b360bdd1a5ff91cf007eca4d52f9.tar.gz
rockbox-688f8decf4c1b360bdd1a5ff91cf007eca4d52f9.tar.bz2
rockbox-688f8decf4c1b360bdd1a5ff91cf007eca4d52f9.tar.xz
Clean up the way empty transfers are sent in error cases.
correctly zero out all data that gets sent to the host I'm just committing this. The actual work was done by Martin Ritter (thanks) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16922 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/usbstack/usb_storage.c44
1 files changed, 23 insertions, 21 deletions
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c
index 0b43376..1f7069d 100644
--- a/firmware/usbstack/usb_storage.c
+++ b/firmware/usbstack/usb_storage.c
@@ -245,6 +245,7 @@ static struct {
static void handle_scsi(struct command_block_wrapper* cbw);
static void send_csw(int status);
static void send_command_result(void *data,int size);
+static void send_command_failed_result(void);
static void send_block_data(void *data,int size);
static void receive_block_data(void *data,int size);
static void identify2inquiry(int lun);
@@ -258,6 +259,7 @@ static enum {
WAITING_FOR_COMMAND,
SENDING_BLOCKS,
SENDING_RESULT,
+ SENDING_FAILED_RESULT,
RECEIVING_BLOCKS,
SENDING_CSW
} state = WAITING_FOR_COMMAND;
@@ -468,6 +470,12 @@ void usb_storage_transfer_complete(bool in,int status,int length)
cur_sense_data.ascq=0;
}
break;
+ case SENDING_FAILED_RESULT:
+ if(in==false) {
+ logf("OUT received in SENDING");
+ }
+ send_csw(UMS_STATUS_FAIL);
+ break;
case SENDING_BLOCKS:
if(in==false) {
logf("OUT received in SENDING");
@@ -657,6 +665,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
case SCSI_REQUEST_SENSE: {
tb.sense_data->ResponseCode=0x70;/*current error*/
+ tb.sense_data->Obsolete=0;
tb.sense_data->fei_sensekey=cur_sense_data.sense_key&0x0f;
tb.sense_data->Information=cur_sense_data.information;
tb.sense_data->AdditionalSenseLength=10;
@@ -673,9 +682,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
case SCSI_MODE_SENSE_10: {
if(! lun_present) {
- /* Windows expects an empty command result before the csw */
- usb_drv_send(usb_endpoint, 0, 0);
- send_csw(UMS_STATUS_FAIL);
+ send_command_failed_result();
cur_sense_data.sense_key=SENSE_NOT_READY;
cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT;
cur_sense_data.ascq=0;
@@ -719,9 +726,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
MIN(sizeof(struct mode_sense_data_10), length));
break;
default:
- /* Windows expects an empty command result before the csw */
- usb_drv_send(usb_endpoint, 0, 0);
- send_csw(UMS_STATUS_FAIL);
+ send_command_failed_result();
cur_sense_data.sense_key=SENSE_ILLEGAL_REQUEST;
cur_sense_data.asc=ASC_INVALID_FIELD_IN_CBD;
cur_sense_data.ascq=0;
@@ -731,9 +736,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
}
case SCSI_MODE_SENSE_6: {
if(! lun_present) {
- /* Windows expects an empty command result before the csw */
- usb_drv_send(usb_endpoint, 0, 0);
- send_csw(UMS_STATUS_FAIL);
+ send_command_failed_result();
cur_sense_data.sense_key=SENSE_NOT_READY;
cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT;
cur_sense_data.ascq=0;
@@ -776,9 +779,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
MIN(sizeof(struct mode_sense_data_6), length));
break;
default:
- /* Windows expects an empty command result before the csw */
- usb_drv_send(usb_endpoint, 0, 0);
- send_csw(UMS_STATUS_FAIL);
+ send_command_failed_result();
cur_sense_data.sense_key=SENSE_ILLEGAL_REQUEST;
cur_sense_data.asc=ASC_INVALID_FIELD_IN_CBD;
cur_sense_data.ascq=0;
@@ -827,9 +828,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
}
else
{
- /* Windows expects an empty command result before the csw */
- usb_drv_send(usb_endpoint, 0, 0);
- send_csw(UMS_STATUS_FAIL);
+ send_command_failed_result();
cur_sense_data.sense_key=SENSE_NOT_READY;
cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT;
cur_sense_data.ascq=0;
@@ -851,9 +850,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
}
else
{
- /* Windows expects an empty command result before the csw */
- usb_drv_send(usb_endpoint, 0, 0);
- send_csw(UMS_STATUS_FAIL);
+ send_command_failed_result();
cur_sense_data.sense_key=SENSE_NOT_READY;
cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT;
cur_sense_data.ascq=0;
@@ -864,9 +861,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
case SCSI_READ_10:
logf("scsi read10 %d",lun);
if(! lun_present) {
- /* Windows expects an empty command result before the csw */
- usb_drv_send(usb_endpoint, 0, 0);
- send_csw(UMS_STATUS_FAIL);
+ send_command_failed_result();
cur_sense_data.sense_key=SENSE_NOT_READY;
cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT;
cur_sense_data.ascq=0;
@@ -957,6 +952,12 @@ static void send_command_result(void *data,int size)
state = SENDING_RESULT;
}
+static void send_command_failed_result(void)
+{
+ usb_drv_send_nonblocking(usb_endpoint, NULL, 0);
+ state = SENDING_FAILED_RESULT;
+}
+
static void receive_block_data(void *data,int size)
{
usb_drv_recv(usb_endpoint, data, size);
@@ -1026,6 +1027,7 @@ static void identify2inquiry(int lun)
tb.inquiry->DeviceType = DIRECT_ACCESS_DEVICE;
tb.inquiry->AdditionalLength = 0x1f;
+ memset(tb.inquiry->Reserved, 0, 3);
tb.inquiry->Versions = 4; /* SPC-2 */
tb.inquiry->Format = 2; /* SPC-2/3 inquiry format */
='n397' href='#n397'>397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422
/* libFLAC - Free Lossless Audio Codec library
 * Copyright (C) 2000,2001,2002,2003,2004,2005  Josh Coalson
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * - Neither the name of the Xiph.org Foundation nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <math.h>
#include "private/bitmath.h"
#include "private/fixed.h"
#include "FLAC/assert.h"

#ifndef M_LN2
/* math.h in VC++ doesn't seem to have this (how Microsoft is that?) */
#define M_LN2 0.69314718055994530942
#endif

#ifdef min
#undef min
#endif
#define min(x,y) ((x) < (y)? (x) : (y))

#ifdef local_abs
#undef local_abs
#endif
#define local_abs(x) ((unsigned)((x)<0? -(x) : (x)))

#ifdef FLAC__INTEGER_ONLY_LIBRARY
/* rbps stands for residual bits per sample
 *
 *             (ln(2) * err)
 * rbps = log  (-----------)
 *           2 (     n     )
 */
static FLAC__fixedpoint local__compute_rbps_integerized(FLAC__uint32 err, FLAC__uint32 n)
{
	FLAC__uint32 rbps;
	unsigned bits; /* the number of bits required to represent a number */
	int fracbits; /* the number of bits of rbps that comprise the fractional part */

	FLAC__ASSERT(sizeof(rbps) == sizeof(FLAC__fixedpoint));
	FLAC__ASSERT(err > 0);
	FLAC__ASSERT(n > 0);

	FLAC__ASSERT(n <= FLAC__MAX_BLOCK_SIZE);
	if(err <= n)
		return 0;
	/*
	 * The above two things tell us 1) n fits in 16 bits; 2) err/n > 1.
	 * These allow us later to know we won't lose too much precision in the
	 * fixed-point division (err<<fracbits)/n.
	 */

	fracbits = (8*sizeof(err)) - (FLAC__bitmath_ilog2(err)+1);

	err <<= fracbits;
	err /= n;
	/* err now holds err/n with fracbits fractional bits */

	/*
	 * Whittle err down to 16 bits max.  16 significant bits is enough for
	 * our purposes.
	 */
	FLAC__ASSERT(err > 0);
	bits = FLAC__bitmath_ilog2(err)+1;
	if(bits > 16) {
		err >>= (bits-16);
		fracbits -= (bits-16);
	}
	rbps = (FLAC__uint32)err;

	/* Multiply by fixed-point version of ln(2), with 16 fractional bits */
	rbps *= FLAC__FP_LN2;
	fracbits += 16;
	FLAC__ASSERT(fracbits >= 0);

	/* FLAC__fixedpoint_log2 requires fracbits%4 to be 0 */
	{
		const int f = fracbits & 3;
		if(f) {
			rbps >>= f;
			fracbits -= f;
		}
	}

	rbps = FLAC__fixedpoint_log2(rbps, fracbits, (unsigned)(-1));

	if(rbps == 0)
		return 0;

	/*
	 * The return value must have 16 fractional bits.  Since the whole part
	 * of the base-2 log of a 32 bit number must fit in 5 bits, and fracbits
	 * must be >= -3, these assertion allows us to be able to shift rbps
	 * left if necessary to get 16 fracbits without losing any bits of the
	 * whole part of rbps.
	 *
	 * There is a slight chance due to accumulated error that the whole part
	 * will require 6 bits, so we use 6 in the assertion.  Really though as
	 * long as it fits in 13 bits (32 - (16 - (-3))) we are fine.
	 */
	FLAC__ASSERT((int)FLAC__bitmath_ilog2(rbps)+1 <= fracbits + 6);
	FLAC__ASSERT(fracbits >= -3);

	/* now shift the decimal point into place */
	if(fracbits < 16)
		return rbps << (16-fracbits);
	else if(fracbits > 16)
		return rbps >> (fracbits-16);
	else
		return rbps;
}

static FLAC__fixedpoint local__compute_rbps_wide_integerized(FLAC__uint64 err, FLAC__uint32 n)
{
	FLAC__uint32 rbps;
	unsigned bits; /* the number of bits required to represent a number */
	int fracbits; /* the number of bits of rbps that comprise the fractional part */

	FLAC__ASSERT(sizeof(rbps) == sizeof(FLAC__fixedpoint));
	FLAC__ASSERT(err > 0);
	FLAC__ASSERT(n > 0);

	FLAC__ASSERT(n <= FLAC__MAX_BLOCK_SIZE);
	if(err <= n)
		return 0;
	/*
	 * The above two things tell us 1) n fits in 16 bits; 2) err/n > 1.
	 * These allow us later to know we won't lose too much precision in the
	 * fixed-point division (err<<fracbits)/n.
	 */

	fracbits = (8*sizeof(err)) - (FLAC__bitmath_ilog2_wide(err)+1);

	err <<= fracbits;
	err /= n;
	/* err now holds err/n with fracbits fractional bits */

	/*
	 * Whittle err down to 16 bits max.  16 significant bits is enough for
	 * our purposes.
	 */
	FLAC__ASSERT(err > 0);
	bits = FLAC__bitmath_ilog2_wide(err)+1;
	if(bits > 16) {
		err >>= (bits-16);
		fracbits -= (bits-16);
	}
	rbps = (FLAC__uint32)err;

	/* Multiply by fixed-point version of ln(2), with 16 fractional bits */
	rbps *= FLAC__FP_LN2;
	fracbits += 16;
	FLAC__ASSERT(fracbits >= 0);

	/* FLAC__fixedpoint_log2 requires fracbits%4 to be 0 */
	{
		const int f = fracbits & 3;
		if(f) {
			rbps >>= f;
			fracbits -= f;
		}
	}

	rbps = FLAC__fixedpoint_log2(rbps, fracbits, (unsigned)(-1));

	if(rbps == 0)
		return 0;

	/*
	 * The return value must have 16 fractional bits.  Since the whole part
	 * of the base-2 log of a 32 bit number must fit in 5 bits, and fracbits
	 * must be >= -3, these assertion allows us to be able to shift rbps
	 * left if necessary to get 16 fracbits without losing any bits of the
	 * whole part of rbps.
	 *
	 * There is a slight chance due to accumulated error that the whole part
	 * will require 6 bits, so we use 6 in the assertion.  Really though as
	 * long as it fits in 13 bits (32 - (16 - (-3))) we are fine.
	 */
	FLAC__ASSERT((int)FLAC__bitmath_ilog2(rbps)+1 <= fracbits + 6);
	FLAC__ASSERT(fracbits >= -3);

	/* now shift the decimal point into place */
	if(fracbits < 16)
		return rbps << (16-fracbits);
	else if(fracbits > 16)
		return rbps >> (fracbits-16);
	else
		return rbps;
}
#endif

#ifndef FLAC__INTEGER_ONLY_LIBRARY
unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1])
#else
unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1])
#endif
{
	FLAC__int32 last_error_0 = data[-1];
	FLAC__int32 last_error_1 = data[-1] - data[-2];
	FLAC__int32 last_error_2 = last_error_1 - (data[-2] - data[-3]);
	FLAC__int32 last_error_3 = last_error_2 - (data[-2] - 2*data[-3] + data[-4]);
	FLAC__int32 error, save;
	FLAC__uint32 total_error_0 = 0, total_error_1 = 0, total_error_2 = 0, total_error_3 = 0, total_error_4 = 0;
	unsigned i, order;

	for(i = 0; i < data_len; i++) {
		error  = data[i]     ; total_error_0 += local_abs(error);                      save = error;
		error -= last_error_0; total_error_1 += local_abs(error); last_error_0 = save; save = error;
		error -= last_error_1; total_error_2 += local_abs(error); last_error_1 = save; save = error;
		error -= last_error_2; total_error_3 += local_abs(error); last_error_2 = save; save = error;
		error -= last_error_3; total_error_4 += local_abs(error); last_error_3 = save;
	}

	if(total_error_0 < min(min(min(total_error_1, total_error_2), total_error_3), total_error_4))
		order = 0;
	else if(total_error_1 < min(min(total_error_2, total_error_3), total_error_4))
		order = 1;
	else if(total_error_2 < min(total_error_3, total_error_4))
		order = 2;
	else if(total_error_3 < total_error_4)
		order = 3;
	else
		order = 4;

	/* Estimate the expected number of bits per residual signal sample. */
	/* 'total_error*' is linearly related to the variance of the residual */
	/* signal, so we use it directly to compute E(|x|) */
	FLAC__ASSERT(data_len > 0 || total_error_0 == 0);
	FLAC__ASSERT(data_len > 0 || total_error_1 == 0);
	FLAC__ASSERT(data_len > 0 || total_error_2 == 0);
	FLAC__ASSERT(data_len > 0 || total_error_3 == 0);
	FLAC__ASSERT(data_len > 0 || total_error_4 == 0);
#ifndef FLAC__INTEGER_ONLY_LIBRARY
	residual_bits_per_sample[0] = (FLAC__float)((total_error_0 > 0) ? log(M_LN2 * (FLAC__double)total_error_0 / (FLAC__double)data_len) / M_LN2 : 0.0);
	residual_bits_per_sample[1] = (FLAC__float)((total_error_1 > 0) ? log(M_LN2 * (FLAC__double)total_error_1 / (FLAC__double)data_len) / M_LN2 : 0.0);
	residual_bits_per_sample[2] = (FLAC__float)((total_error_2 > 0) ? log(M_LN2 * (FLAC__double)total_error_2 / (FLAC__double)data_len) / M_LN2 : 0.0);
	residual_bits_per_sample[3] = (FLAC__float)((total_error_3 > 0) ? log(M_LN2 * (FLAC__double)total_error_3 / (FLAC__double)data_len) / M_LN2 : 0.0);
	residual_bits_per_sample[4] = (FLAC__float)((total_error_4 > 0) ? log(M_LN2 * (FLAC__double)total_error_4 / (FLAC__double)data_len) / M_LN2 : 0.0);
#else
	residual_bits_per_sample[0] = (total_error_0 > 0) ? local__compute_rbps_integerized(total_error_0, data_len) : 0;
	residual_bits_per_sample[1] = (total_error_1 > 0) ? local__compute_rbps_integerized(total_error_1, data_len) : 0;
	residual_bits_per_sample[2] = (total_error_2 > 0) ? local__compute_rbps_integerized(total_error_2, data_len) : 0;
	residual_bits_per_sample[3] = (total_error_3 > 0) ? local__compute_rbps_integerized(total_error_3, data_len) : 0;
	residual_bits_per_sample[4] = (total_error_4 > 0) ? local__compute_rbps_integerized(total_error_4, data_len) : 0;
#endif

	return order;
}

#ifndef FLAC__INTEGER_ONLY_LIBRARY
unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1])
#else
unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsigned data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1])
#endif
{
	FLAC__int32 last_error_0 = data[-1];
	FLAC__int32 last_error_1 = data[-1] - data[-2];
	FLAC__int32 last_error_2 = last_error_1 - (data[-2] - data[-3]);
	FLAC__int32 last_error_3 = last_error_2 - (data[-2] - 2*data[-3] + data[-4]);
	FLAC__int32 error, save;
	/* total_error_* are 64-bits to avoid overflow when encoding
	 * erratic signals when the bits-per-sample and blocksize are
	 * large.
	 */
	FLAC__uint64 total_error_0 = 0, total_error_1 = 0, total_error_2 = 0, total_error_3 = 0, total_error_4 = 0;
	unsigned i, order;

	for(i = 0; i < data_len; i++) {
		error  = data[i]     ; total_error_0 += local_abs(error);                      save = error;
		error -= last_error_0; total_error_1 += local_abs(error); last_error_0 = save; save = error;
		error -= last_error_1; total_error_2 += local_abs(error); last_error_1 = save; save = error;
		error -= last_error_2; total_error_3 += local_abs(error); last_error_2 = save; save = error;
		error -= last_error_3; total_error_4 += local_abs(error); last_error_3 = save;
	}

	if(total_error_0 < min(min(min(total_error_1, total_error_2), total_error_3), total_error_4))
		order = 0;
	else if(total_error_1 < min(min(total_error_2, total_error_3), total_error_4))
		order = 1;
	else if(total_error_2 < min(total_error_3, total_error_4))
		order = 2;
	else if(total_error_3 < total_error_4)
		order = 3;
	else
		order = 4;

	/* Estimate the expected number of bits per residual signal sample. */
	/* 'total_error*' is linearly related to the variance of the residual */
	/* signal, so we use it directly to compute E(|x|) */
	FLAC__ASSERT(data_len > 0 || total_error_0 == 0);
	FLAC__ASSERT(data_len > 0 || total_error_1 == 0);
	FLAC__ASSERT(data_len > 0 || total_error_2 == 0);
	FLAC__ASSERT(data_len > 0 || total_error_3 == 0);
	FLAC__ASSERT(data_len > 0 || total_error_4 == 0);
#ifndef FLAC__INTEGER_ONLY_LIBRARY
#if defined _MSC_VER || defined __MINGW32__
	/* with MSVC you have to spoon feed it the casting */
	residual_bits_per_sample[0] = (FLAC__float)((total_error_0 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_0 / (FLAC__double)data_len) / M_LN2 : 0.0);
	residual_bits_per_sample[1] = (FLAC__float)((total_error_1 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_1 / (FLAC__double)data_len) / M_LN2 : 0.0);
	residual_bits_per_sample[2] = (FLAC__float)((total_error_2 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_2 / (FLAC__double)data_len) / M_LN2 : 0.0);
	residual_bits_per_sample[3] = (FLAC__float)((total_error_3 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_3 / (FLAC__double)data_len) / M_LN2 : 0.0);
	residual_bits_per_sample[4] = (FLAC__float)((total_error_4 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_4 / (FLAC__double)data_len) / M_LN2 : 0.0);
#else
	residual_bits_per_sample[0] = (FLAC__float)((total_error_0 > 0) ? log(M_LN2 * (FLAC__double)total_error_0 / (FLAC__double)data_len) / M_LN2 : 0.0);
	residual_bits_per_sample[1] = (FLAC__float)((total_error_1 > 0) ? log(M_LN2 * (FLAC__double)total_error_1 / (FLAC__double)data_len) / M_LN2 : 0.0);
	residual_bits_per_sample[2] = (FLAC__float)((total_error_2 > 0) ? log(M_LN2 * (FLAC__double)total_error_2 / (FLAC__double)data_len) / M_LN2 : 0.0);
	residual_bits_per_sample[3] = (FLAC__float)((total_error_3 > 0) ? log(M_LN2 * (FLAC__double)total_error_3 / (FLAC__double)data_len) / M_LN2 : 0.0);
	residual_bits_per_sample[4] = (FLAC__float)((total_error_4 > 0) ? log(M_LN2 * (FLAC__double)total_error_4 / (FLAC__double)data_len) / M_LN2 : 0.0);
#endif
#else
	residual_bits_per_sample[0] = (total_error_0 > 0) ? local__compute_rbps_wide_integerized(total_error_0, data_len) : 0;
	residual_bits_per_sample[1] = (total_error_1 > 0) ? local__compute_rbps_wide_integerized(total_error_1, data_len) : 0;
	residual_bits_per_sample[2] = (total_error_2 > 0) ? local__compute_rbps_wide_integerized(total_error_2, data_len) : 0;
	residual_bits_per_sample[3] = (total_error_3 > 0) ? local__compute_rbps_wide_integerized(total_error_3, data_len) : 0;
	residual_bits_per_sample[4] = (total_error_4 > 0) ? local__compute_rbps_wide_integerized(total_error_4, data_len) : 0;
#endif