/* ** AlacDecodeUtils.java ** ** Copyright (c) 2011 Peter McQuillan ** ** All Rights Reserved. ** ** Distributed under the BSD Software License (see license.txt) ** */ package com.beatofthedrum.alacdecoder; class AlacDecodeUtils { public static void alac_set_info(AlacFile alac, int[] inputbuffer) { int ptrIndex = 0; ptrIndex += 4; // size ptrIndex += 4; // frma ptrIndex += 4; // alac ptrIndex += 4; // size ptrIndex += 4; // alac ptrIndex += 4; // 0 ? alac.setinfo_max_samples_per_frame = ((inputbuffer[ptrIndex] << 24) + (inputbuffer[ptrIndex+1] << 16) + (inputbuffer[ptrIndex+2] << 8) + inputbuffer[ptrIndex+3]); // buffer size / 2 ? ptrIndex += 4; alac.setinfo_7a = inputbuffer[ptrIndex]; ptrIndex += 1; alac.setinfo_sample_size = inputbuffer[ptrIndex]; ptrIndex += 1; alac.setinfo_rice_historymult = (inputbuffer[ptrIndex] & 0xff); ptrIndex += 1; alac.setinfo_rice_initialhistory = (inputbuffer[ptrIndex] & 0xff); ptrIndex += 1; alac.setinfo_rice_kmodifier = (inputbuffer[ptrIndex] & 0xff); ptrIndex += 1; alac.setinfo_7f = inputbuffer[ptrIndex]; ptrIndex += 1; alac.setinfo_80 = (inputbuffer[ptrIndex] << 8) + inputbuffer[ptrIndex+1]; ptrIndex += 2; alac.setinfo_82 = ((inputbuffer[ptrIndex] << 24) + (inputbuffer[ptrIndex+1] << 16) + (inputbuffer[ptrIndex+2] << 8) + inputbuffer[ptrIndex+3]); ptrIndex += 4; alac.setinfo_86 = ((inputbuffer[ptrIndex] << 24) + (inputbuffer[ptrIndex+1] << 16) + (inputbuffer[ptrIndex+2] << 8) + inputbuffer[ptrIndex+3]); ptrIndex += 4; alac.setinfo_8a_rate = ((inputbuffer[ptrIndex] << 24) + (inputbuffer[ptrIndex+1] << 16) + (inputbuffer[ptrIndex+2] << 8) + inputbuffer[ptrIndex+3]); ptrIndex += 4; } /* stream reading */ /* supports reading 1 to 16 bits, in big endian format */ static int readbits_16(AlacFile alac, int bits ) { int result = 0; int new_accumulator = 0; int part1 = 0; int part2 = 0; int part3 =0; part1 = (alac.input_buffer[alac.ibIdx] & 0xff); part2 = (alac.input_buffer[alac.ibIdx + 1] & 0xff); part3 = (alac.input_buffer[alac.ibIdx + 2] & 0xff); result = ((part1 << 16) | (part2 << 8) | part3); /* shift left by the number of bits we've already read, * so that the top 'n' bits of the 24 bits we read will * be the return bits */ result = result << alac.input_buffer_bitaccumulator; result = result & 0x00ffffff; /* and then only want the top 'n' bits from that, where * n is 'bits' */ result = result >> (24 - bits); new_accumulator = (alac.input_buffer_bitaccumulator + bits); /* increase the buffer pointer if we've read over n bytes. */ alac.ibIdx += (new_accumulator >> 3); /* and the remainder goes back into the bit accumulator */ alac.input_buffer_bitaccumulator = (new_accumulator & 7); return result; } /* supports reading 1 to 32 bits, in big endian format */ static int readbits(AlacFile alac, int bits ) { int result = 0; if (bits > 16) { bits -= 16; result = readbits_16(alac, 16) << bits; } result |= readbits_16(alac, bits); return result; } /* reads a single bit */ static int readbit(AlacFile alac) { int result = 0; int new_accumulator = 0; int part1 = 0; part1 = (alac.input_buffer[alac.ibIdx] & 0xff); result = part1; result = result << alac.input_buffer_bitaccumulator; result = result >> 7 & 1; new_accumulator = (alac.input_buffer_bitaccumulator + 1); alac.ibIdx += new_accumulator / 8; alac.input_buffer_bitaccumulator = (new_accumulator % 8); return result; } static void unreadbits(AlacFile alac, int bits ) { int new_accumulator = (alac.input_buffer_bitaccumulator - bits); alac.ibIdx += (new_accumulator >> 3); alac.input_buffer_bitaccumulator = (new_accumulator & 7); if (alac.input_buffer_bitaccumulator < 0) alac.input_buffer_bitaccumulator *= -1; } static LeadingZeros count_leading_zeros_extra(int curbyte, int output, LeadingZeros lz) { if ((curbyte & 0xf0)==0) { output += 4; } else curbyte = curbyte >> 4; if ((curbyte & 0x8) != 0) { lz.output = output; lz.curbyte = curbyte; return lz; } if ((curbyte & 0x4) != 0) { lz.output = output + 1; lz.curbyte = curbyte; return lz; } if ((curbyte & 0x2) != 0) { lz.output = output + 2; lz.curbyte = curbyte; return lz; } if ((curbyte & 0x1) != 0) { lz.output = output + 3; lz.curbyte = curbyte; return lz; } /* shouldn't get here: */ lz.output = output + 4; lz.curbyte = curbyte; return lz; } static int count_leading_zeros(int input, LeadingZeros lz) { int output = 0; int curbyte = 0; curbyte = input >> 24; if (curbyte != 0) { count_leading_zeros_extra(curbyte, output, lz); output = lz.output; curbyte = lz.curbyte; return output; } output += 8; curbyte = input >> 16; if ((curbyte & 0xFF) != 0) { count_leading_zeros_extra(curbyte, output, lz); output = lz.output; curbyte = lz.curbyte; return output; } output += 8; curbyte = input >> 8; if ((curbyte & 0xFF) != 0) { count_leading_zeros_extra(curbyte, output, lz); output = lz.output; curbyte = lz.curbyte; return output; } output += 8; curbyte = input; if ((curbyte & 0xFF) != 0) { count_leading_zeros_extra(curbyte, output, lz); output = lz.output; curbyte = lz.curbyte; return output; } output += 8; return output; } public static int entropy_decode_value(AlacFile alac, int readSampleSize , int k , int rice_kmodifier_mask ) { int x = 0; // decoded value // read x, number of 1s before 0 represent the rice value. while (x <= Defines.RICE_THRESHOLD && readbit(alac) != 0) { x++; } if (x > Defines.RICE_THRESHOLD) { // read the number from the bit stream (raw value) int value = 0; value = readbits(alac, readSampleSize); // mask value value &= ((0xffffffff) >> (32 - readSampleSize)); x = value; } else { if (k != 1) { int extraBits = readbits(alac, k); x *= (((1 << k) - 1) & rice_kmodifier_mask); if (extraBits > 1) x += extraBits - 1; else unreadbits(alac, 1); } } return x; } public static void entropy_rice_decode(AlacFile alac, int[] outputBuffer, int outputSize , int readSampleSize , int rice_initialhistory , int rice_kmodifier , int rice_historymult , int rice_kmodifier_mask ) { int history = rice_initialhistory; int outputCount = 0; int signModifier = 0; while(outputCount < outputSize) { int decodedValue = 0; int finalValue = 0; int k = 0; k = 31 - rice_kmodifier - count_leading_zeros((history >> 9) + 3, alac.lz); if (k < 0) k += rice_kmodifier; else k = rice_kmodifier; // note: don't use rice_kmodifier_mask here (set mask to 0xFFFFFFFF) decodedValue = entropy_decode_value(alac, readSampleSize, k, 0xFFFFFFFF); decodedValue += signModifier; finalValue = ((decodedValue + 1) / 2); // inc by 1 and shift out sign bit if ((decodedValue & 1) != 0) // the sign is stored in the low bit finalValue *= -1; outputBuffer[outputCount] = finalValue; signModifier = 0; // update history history += (decodedValue * rice_historymult) - ((history * rice_historymult) >> 9); if (decodedValue > 0xFFFF) history = 0xFFFF; // special case, for compressed blocks of 0 if ((history < 128) && (outputCount + 1 < outputSize)) { int blockSize = 0; signModifier = 1; k = count_leading_zeros(history, alac.lz) + ((history + 16) / 64) - 24; // note: blockSize is always 16bit blockSize = entropy_decode_value(alac, 16, k, rice_kmodifier_mask); // got blockSize 0s if (blockSize > 0) { int countSize = 0; countSize = blockSize; for (int j = 0; j < countSize; j++) { outputBuffer[outputCount + 1 + j] = 0; } outputCount += blockSize; } if (blockSize > 0xFFFF) signModifier = 0; history = 0; } outputCount++; } } static int[] predictor_decompress_fir_adapt(int[] error_buffer, int output_size , int readsamplesize , int[] predictor_coef_table, int predictor_coef_num , int predictor_quantitization ) { int buffer_out_idx = 0; int[] buffer_out; int bitsmove = 0; /* first sample always copies */ buffer_out = error_buffer; if (predictor_coef_num == 0) { if (output_size <= 1) return(buffer_out); int sizeToCopy = 0; sizeToCopy = (output_size-1) * 4; System.arraycopy(error_buffer, 1, buffer_out, 1, sizeToCopy); return(buffer_out); } if (predictor_coef_num == 0x1f) // 11111 - max value of predictor_coef_num { /* second-best case scenario for fir decompression, * error describes a small difference from the previous sample only */ if (output_size <= 1) return(buffer_out); for (int i = 0; i < (output_size - 1); i++) { int prev_value = 0; int error_value = 0; prev_value = buffer_out[i]; error_value = error_buffer[i+1]; bitsmove = 32 - readsamplesize; buffer_out[i+1] = (((prev_value + error_value) << bitsmove) >> bitsmove); } return(buffer_out); } /* read warm-up samples */ if (predictor_coef_num > 0) { for (int i = 0; i < predictor_coef_num; i++) { int val = 0; val = buffer_out[i] + error_buffer[i+1]; bitsmove = 32 - readsamplesize; val = ((val << bitsmove) >> bitsmove); buffer_out[i+1] = val; } } /* general case */ if (predictor_coef_num > 0) { buffer_out_idx = 0; for (int i = predictor_coef_num + 1; i < output_size; i++) { int j ; int sum = 0; int outval ; int error_val = error_buffer[i]; for (j = 0; j < predictor_coef_num; j++) { sum += (buffer_out[buffer_out_idx + predictor_coef_num-j] - buffer_out[buffer_out_idx]) * predictor_coef_table[j]; } outval = (1 << (predictor_quantitization-1)) + sum; outval = outval >> predictor_quantitization; outval = outval + buffer_out[buffer_out_idx] + error_val; bitsmove = 32 - readsamplesize; outval = ((outval << bitsmove) >> bitsmove); buffer_out[buffer_out_idx+predictor_coef_num+1] = outval; if (error_val > 0) { int predictor_num = predictor_coef_num - 1; while (predictor_num >= 0 && error_val > 0) { int val = buffer_out[buffer_out_idx] - buffer_out[buffer_out_idx + predictor_coef_num - predictor_num]; int sign = ((val < 0) ? (-1) : ((val > 0) ? (1) : (0))); predictor_coef_table[predictor_num] -= sign; val *= sign; // absolute value error_val -= ((val >> predictor_quantitization) * (predictor_coef_num - predictor_num)); predictor_num--; } } else if (error_val < 0) { int predictor_num = predictor_coef_num - 1; while (predictor_num >= 0 && error_val < 0) { int val = buffer_out[buffer_out_idx] - buffer_out[buffer_out_idx + predictor_coef_num - predictor_num]; int sign = - ((val < 0) ? (-1) : ((val > 0) ? (1) : (0))); predictor_coef_table[predictor_num] -= sign; val *= sign; // neg value error_val -= ((val >> predictor_quantitization) * (predictor_coef_num - predictor_num)); predictor_num--; } } buffer_out_idx++; } } return(buffer_out); } public static void deinterlace_16(int[] buffer_a, int[] buffer_b, int[] buffer_out, int numchannels , int numsamples , int interlacing_shift , int interlacing_leftweight ) { if (numsamples <= 0) return; /* weighted interlacing */ if (0 != interlacing_leftweight) { for (int i = 0; i < numsamples; i++) { int difference = 0; int midright = 0; int left = 0; int right = 0; midright = buffer_a[i]; difference = buffer_b[i]; right = (midright - ((difference * interlacing_leftweight) >> interlacing_shift)); left = (right + difference); /* output is always little endian */ buffer_out[i *numchannels] = left; buffer_out[i *numchannels + 1] = right; } return; } /* otherwise basic interlacing took place */ for (int i = 0; i < numsamples; i++) { int left = 0; int right = 0; left = buffer_a[i]; right = buffer_b[i]; /* output is always little endian */ buffer_out[i *numchannels] = left; buffer_out[i *numchannels + 1] = right; } } public static void deinterlace_24(int[] buffer_a, int[] buffer_b, int uncompressed_bytes , int[] uncompressed_bytes_buffer_a, int[] uncompressed_bytes_buffer_b, int[] buffer_out, int numchannels , int numsamples , int interlacing_shift , int interlacing_leftweight ) { if (numsamples <= 0) return; /* weighted interlacing */ if (interlacing_leftweight != 0) { for (int i = 0; i < numsamples; i++) { int difference = 0; int midright = 0; int left = 0; int right = 0; midright = buffer_a[i]; difference = buffer_b[i]; right = midright - ((difference * interlacing_leftweight) >> interlacing_shift); left = right + difference; if (uncompressed_bytes != 0) { int mask = ~(0xFFFFFFFF << (uncompressed_bytes * 8)); left <<= (uncompressed_bytes * 8); right <<= (uncompressed_bytes * 8); left = left | (uncompressed_bytes_buffer_a[i] & mask); right = right | (uncompressed_bytes_buffer_b[i] & mask); } buffer_out[i * numchannels * 3] = (left & 0xFF); buffer_out[i * numchannels * 3 + 1] = ((left >> 8) & 0xFF); buffer_out[i * numchannels * 3 + 2] = ((left >> 16) & 0xFF); buffer_out[i * numchannels * 3 + 3] = (right & 0xFF); buffer_out[i * numchannels * 3 + 4] = ((right >> 8) & 0xFF); buffer_out[i * numchannels * 3 + 5] = ((right >> 16) & 0xFF); } return; } /* otherwise basic interlacing took place */ for (int i = 0; i < numsamples; i++) { int left = 0; int right = 0; left = buffer_a[i]; right = buffer_b[i]; if (uncompressed_bytes != 0) { int mask = ~(0xFFFFFFFF << (uncompressed_bytes * 8)); left <<= (uncompressed_bytes * 8); right <<= (uncompressed_bytes * 8); left = left | (uncompressed_bytes_buffer_a[i] & mask); right = right | (uncompressed_bytes_buffer_b[i] & mask); } buffer_out[i * numchannels * 3] = (left & 0xFF); buffer_out[i * numchannels * 3 + 1] = ((left >> 8) & 0xFF); buffer_out[i * numchannels * 3 + 2] = ((left >> 16) & 0xFF); buffer_out[i * numchannels * 3 + 3] = (right & 0xFF); buffer_out[i * numchannels * 3 + 4] = ((right >> 8) & 0xFF); buffer_out[i * numchannels * 3 + 5] = ((right >> 16) & 0xFF); } } public static int decode_frame(AlacFile alac, byte[] inbuffer, int[] outbuffer, int outputsize ) { int channels ; int outputsamples = alac.setinfo_max_samples_per_frame; /* setup the stream */ alac.input_buffer = inbuffer; alac.input_buffer_bitaccumulator = 0; alac.ibIdx = 0; channels = readbits(alac, 3); outputsize = outputsamples * alac.bytespersample; if(channels == 0) // 1 channel { int hassize ; int isnotcompressed ; int readsamplesize ; int uncompressed_bytes ; int ricemodifier ; int tempPred = 0; /* 2^result = something to do with output waiting. * perhaps matters if we read > 1 frame in a pass? */ readbits(alac, 4); readbits(alac, 12); // unknown, skip 12 bits hassize = readbits(alac, 1); // the output sample size is stored soon uncompressed_bytes = readbits(alac, 2); // number of bytes in the (compressed) stream that are not compressed isnotcompressed = readbits(alac, 1); // whether the frame is compressed if (hassize != 0) { /* now read the number of samples, * as a 32bit integer */ outputsamples = readbits(alac, 32); outputsize = outputsamples * alac.bytespersample; } readsamplesize = alac.setinfo_sample_size - (uncompressed_bytes * 8); if (isnotcompressed == 0) { // so it is compressed int[] predictor_coef_table = alac.predictor_coef_table; int predictor_coef_num ; int prediction_type ; int prediction_quantitization ; int i ; /* skip 16 bits, not sure what they are. seem to be used in * two channel case */ readbits(alac, 8); readbits(alac, 8); prediction_type = readbits(alac, 4); prediction_quantitization = readbits(alac, 4); ricemodifier = readbits(alac, 3); predictor_coef_num = readbits(alac, 5); /* read the predictor table */ for (i = 0; i < predictor_coef_num; i++) { tempPred = readbits(alac,16); if(tempPred > 32767) { // the predictor coef table values are only 16 bit signed tempPred = tempPred - 65536; } predictor_coef_table[i] = tempPred; } if (uncompressed_bytes != 0) { for (i = 0; i < outputsamples; i++) { alac.uncompressed_bytes_buffer_a[i] = readbits(alac, uncompressed_bytes * 8); } } entropy_rice_decode(alac, alac.predicterror_buffer_a, outputsamples, readsamplesize, alac.setinfo_rice_initialhistory, alac.setinfo_rice_kmodifier, ricemodifier * (alac.setinfo_rice_historymult / 4), (1 << alac.setinfo_rice_kmodifier) - 1); if (prediction_type == 0) { // adaptive fir alac.outputsamples_buffer_a = predictor_decompress_fir_adapt(alac.predicterror_buffer_a, outputsamples, readsamplesize, predictor_coef_table, predictor_coef_num, prediction_quantitization); } else { System.err.println("FIXME: unhandled predicition type: " +prediction_type); /* i think the only other prediction type (or perhaps this is just a * boolean?) runs adaptive fir twice.. like: * predictor_decompress_fir_adapt(predictor_error, tempout, ...) * predictor_decompress_fir_adapt(predictor_error, outputsamples ...) * little strange.. */ } } else { // not compressed, easy case if (alac.setinfo_sample_size <= 16) { int bitsmove = 0; for (int i = 0; i < outputsamples; i++) { int audiobits = readbits(alac, alac.setinfo_sample_size); bitsmove = 32 - alac.setinfo_sample_size; audiobits = ((audiobits << bitsmove) >> bitsmove); alac.outputsamples_buffer_a[i] = audiobits; } } else { int x ; int m = 1 << (24 -1); for (int i = 0; i < outputsamples; i++) { int audiobits ; audiobits = readbits(alac, 16); /* special case of sign extension.. * as we'll be ORing the low 16bits into this */ audiobits = audiobits << (alac.setinfo_sample_size - 16); audiobits = audiobits | readbits(alac, alac.setinfo_sample_size - 16); x = audiobits & ((1 << 24) - 1); audiobits = (x ^ m) - m; // sign extend 24 bits alac.outputsamples_buffer_a[i] = audiobits; } } uncompressed_bytes = 0; // always 0 for uncompressed } switch(alac.setinfo_sample_size) { case 16: { for (int i = 0; i < outputsamples; i++) { int sample = alac.outputsamples_buffer_a[i]; outbuffer[i * alac.numchannels] = sample; /* ** We have to handle the case where the data is actually mono, but the stsd atom says it has 2 channels ** in this case we create a stereo file where one of the channels is silent. If mono and 1 channel this value ** will be overwritten in the next iteration */ outbuffer[(i * alac.numchannels) + 1] = 0; } break; } case 24: { for (int i = 0; i < outputsamples; i++) { int sample = alac.outputsamples_buffer_a[i]; if (uncompressed_bytes != 0) { int mask = 0; sample = sample << (uncompressed_bytes * 8); mask = ~(0xFFFFFFFF << (uncompressed_bytes * 8)); sample = sample | (alac.uncompressed_bytes_buffer_a[i] & mask); } outbuffer[i * alac.numchannels * 3] = ((sample) & 0xFF); outbuffer[i * alac.numchannels * 3 + 1] = ((sample >> 8) & 0xFF); outbuffer[i * alac.numchannels * 3 + 2] = ((sample >> 16) & 0xFF); /* ** We have to handle the case where the data is actually mono, but the stsd atom says it has 2 channels ** in this case we create a stereo file where one of the channels is silent. If mono and 1 channel this value ** will be overwritten in the next iteration */ outbuffer[i * alac.numchannels * 3 + 3] = 0; outbuffer[i * alac.numchannels * 3 + 4] = 0; outbuffer[i * alac.numchannels * 3 + 5] = 0; } break; } case 20: case 32: System.err.println("FIXME: unimplemented sample size " + alac.setinfo_sample_size); default: } } else if(channels == 1) // 2 channels { int hassize ; int isnotcompressed ; int readsamplesize ; int uncompressed_bytes ; int interlacing_shift ; int interlacing_leftweight ; /* 2^result = something to do with output waiting. * perhaps matters if we read > 1 frame in a pass? */ readbits(alac, 4); readbits(alac, 12); // unknown, skip 12 bits hassize = readbits(alac, 1); // the output sample size is stored soon uncompressed_bytes = readbits(alac, 2); // the number of bytes in the (compressed) stream that are not compressed isnotcompressed = readbits(alac, 1); // whether the frame is compressed if (hassize != 0) { /* now read the number of samples, * as a 32bit integer */ outputsamples = readbits(alac, 32); outputsize = outputsamples * alac.bytespersample; } readsamplesize = alac.setinfo_sample_size - (uncompressed_bytes * 8) + 1; if (isnotcompressed == 0) { // compressed int[] predictor_coef_table_a = alac.predictor_coef_table_a; int predictor_coef_num_a ; int prediction_type_a ; int prediction_quantitization_a ; int ricemodifier_a ; int[] predictor_coef_table_b = alac.predictor_coef_table_b; int predictor_coef_num_b ; int prediction_type_b ; int prediction_quantitization_b ; int ricemodifier_b ; int tempPred = 0; interlacing_shift = readbits(alac, 8); interlacing_leftweight = readbits(alac, 8); /******** channel 1 ***********/ prediction_type_a = readbits(alac, 4); prediction_quantitization_a = readbits(alac, 4); ricemodifier_a = readbits(alac, 3); predictor_coef_num_a = readbits(alac, 5); /* read the predictor table */ for (int i = 0; i < predictor_coef_num_a; i++) { tempPred = readbits(alac,16); if(tempPred > 32767) { // the predictor coef table values are only 16 bit signed tempPred = tempPred - 65536; } predictor_coef_table_a[i] = tempPred; } /******** channel 2 *********/ prediction_type_b = readbits(alac, 4); prediction_quantitization_b = readbits(alac, 4); ricemodifier_b = readbits(alac, 3); predictor_coef_num_b = readbits(alac, 5); /* read the predictor table */ for (int i = 0; i < predictor_coef_num_b; i++) { tempPred = readbits(alac,16); if(tempPred > 32767) { // the predictor coef table values are only 16 bit signed tempPred = tempPred - 65536; } predictor_coef_table_b[i] = tempPred; } /*********************/ if (uncompressed_bytes != 0) { // see mono case for (int i = 0; i < outputsamples; i++) { alac.uncompressed_bytes_buffer_a[i] = readbits(alac, uncompressed_bytes * 8); alac.uncompressed_bytes_buffer_b[i] = readbits(alac, uncompressed_bytes * 8); } } /* channel 1 */ entropy_rice_decode(alac, alac.predicterror_buffer_a, outputsamples, readsamplesize, alac.setinfo_rice_initialhistory, alac.setinfo_rice_kmodifier, ricemodifier_a * (alac.setinfo_rice_historymult / 4), (1 << alac.setinfo_rice_kmodifier) - 1); if (prediction_type_a == 0) { // adaptive fir alac.outputsamples_buffer_a = predictor_decompress_fir_adapt(alac.predicterror_buffer_a, outputsamples, readsamplesize, predictor_coef_table_a, predictor_coef_num_a, prediction_quantitization_a); } else { // see mono case System.err.println("FIXME: unhandled predicition type: " + prediction_type_a); } /* channel 2 */ entropy_rice_decode(alac, alac.predicterror_buffer_b, outputsamples, readsamplesize, alac.setinfo_rice_initialhistory, alac.setinfo_rice_kmodifier, ricemodifier_b * (alac.setinfo_rice_historymult / 4), (1 << alac.setinfo_rice_kmodifier) - 1); if (prediction_type_b == 0) { // adaptive fir alac.outputsamples_buffer_b = predictor_decompress_fir_adapt(alac.predicterror_buffer_b, outputsamples, readsamplesize, predictor_coef_table_b, predictor_coef_num_b, prediction_quantitization_b); } else { System.err.println("FIXME: unhandled predicition type: " + prediction_type_b); } } else { // not compressed, easy case if (alac.setinfo_sample_size <= 16) { int bitsmove ; for (int i = 0; i < outputsamples; i++) { int audiobits_a ; int audiobits_b ; audiobits_a = readbits(alac, alac.setinfo_sample_size); audiobits_b = readbits(alac, alac.setinfo_sample_size); bitsmove = 32 - alac.setinfo_sample_size; audiobits_a = ((audiobits_a << bitsmove) >> bitsmove); audiobits_b = ((audiobits_b << bitsmove) >> bitsmove); alac.outputsamples_buffer_a[i] = audiobits_a; alac.outputsamples_buffer_b[i] = audiobits_b; } } else { int x ; int m = 1 << (24 -1); for (int i = 0; i < outputsamples; i++) { int audiobits_a ; int audiobits_b ; audiobits_a = readbits(alac, 16); audiobits_a = audiobits_a << (alac.setinfo_sample_size - 16); audiobits_a = audiobits_a | readbits(alac, alac.setinfo_sample_size - 16); x = audiobits_a & ((1 << 24) - 1); audiobits_a = (x ^ m) - m; // sign extend 24 bits audiobits_b = readbits(alac, 16); audiobits_b = audiobits_b << (alac.setinfo_sample_size - 16); audiobits_b = audiobits_b | readbits(alac, alac.setinfo_sample_size - 16); x = audiobits_b & ((1 << 24) - 1); audiobits_b = (x ^ m) - m; // sign extend 24 bits alac.outputsamples_buffer_a[i] = audiobits_a; alac.outputsamples_buffer_b[i] = audiobits_b; } } uncompressed_bytes = 0; // always 0 for uncompressed interlacing_shift = 0; interlacing_leftweight = 0; } switch(alac.setinfo_sample_size) { case 16: { deinterlace_16(alac.outputsamples_buffer_a, alac.outputsamples_buffer_b, outbuffer, alac.numchannels, outputsamples, interlacing_shift, interlacing_leftweight); break; } case 24: { deinterlace_24(alac.outputsamples_buffer_a, alac.outputsamples_buffer_b, uncompressed_bytes, alac.uncompressed_bytes_buffer_a, alac.uncompressed_bytes_buffer_b, outbuffer, alac.numchannels, outputsamples, interlacing_shift, interlacing_leftweight); break; } case 20: case 32: System.err.println("FIXME: unimplemented sample size " + alac.setinfo_sample_size); default: } } return outputsize; } public static AlacFile create_alac(int samplesize , int numchannels ) { AlacFile newfile = new AlacFile(); newfile.samplesize = samplesize; newfile.numchannels = numchannels; newfile.bytespersample = (samplesize / 8) * numchannels; return newfile; } }