/* ** DecoderDemo.java ** ** Copyright (c) 2011 Peter McQuillan ** ** All Rights Reserved. ** ** Distributed under the BSD Software License (see license.txt) ** */ import com.beatofthedrum.alacdecoder.*; class DecoderDemo { static java.io.FileOutputStream output_stream; static int output_opened; static int write_wav_format = 1; static String input_file_n = ""; static String output_file_n = ""; // Reformat samples from longs in processor's native endian mode to // little-endian data with (possibly) less than 3 bytes / sample. public static byte[] format_samples(int bps, int[] src, int samcnt) { int temp = 0; int counter = 0; int counter2 = 0; byte[] dst = new byte[65536]; switch (bps) { case 1: while (samcnt > 0) { dst[counter] = (byte)(0x00FF & (src[counter] + 128)); counter++; samcnt--; } break; case 2: while (samcnt > 0) { temp = src[counter2]; dst[counter] = (byte)temp; counter++; dst[counter] = (byte)(temp >>> 8); counter++; counter2++; samcnt = samcnt - 2; } break; case 3: while (samcnt > 0) { dst[counter] = (byte)src[counter2]; counter++; counter2++; samcnt--; } break; } return dst; } static void setup_environment(int argc, String[] argv) { int i = argc; int escaped = 0; if (argc < 2) usage(); int arg_idx = 0; // loop through command-line arguments while (arg_idx < argc) { if (argv[arg_idx].startsWith("-")) { if (argv[arg_idx].startsWith("-r") || argv[arg_idx].startsWith("-R")) { // raw PCM output write_wav_format = 0; } } else if (input_file_n.length() == 0) { input_file_n = argv[arg_idx]; } else if (output_file_n.length() == 0) { output_file_n = argv[arg_idx]; } else { System.out.println("extra unknown argument: " + argv[arg_idx]); usage(); } arg_idx++; } if (input_file_n.length() == 0 || output_file_n.length() == 0 ) usage(); } static void GetBuffer(AlacContext ac) { int destBufferSize = 1024 *24 * 3; // 24kb buffer = 4096 frames = 1 alac sample (we support max 24bps) byte[] pcmBuffer = new byte[65536]; int total_unpacked_bytes = 0; int bytes_unpacked; int[] pDestBuffer = new int[destBufferSize]; int bps = AlacUtils.AlacGetBytesPerSample(ac); while (true) { bytes_unpacked = AlacUtils.AlacUnpackSamples(ac, pDestBuffer); total_unpacked_bytes += bytes_unpacked; if (bytes_unpacked > 0) { pcmBuffer = format_samples(bps, pDestBuffer, bytes_unpacked); try { output_stream.write(pcmBuffer, 0, bytes_unpacked); } catch(java.io.IOException ioe) { System.err.println("Error writing data to output file. Error: " + ioe); } } if (bytes_unpacked == 0) break; } // end of while } static void usage() { System.out.println("Usage: alac [options] inputfile outputfile"); System.out.println("Decompresses the ALAC file specified"); System.out.println("Options:"); System.out.println(" -r write output as raw PCM data. Default"); System.out.println(" is in WAV format."); System.out.println(""); System.out.println("This port of the code is (c) Peter McQuillan 2011"); System.out.println("Original software is (c) 2005 David Hammerton"); System.exit(1); } public static void main(String [] args) { AlacContext ac = new AlacContext(); int output_size; int total_samples; int sample_rate; int num_channels; int byteps; int bitps; output_opened = 0; setup_environment(args.length, args); // checks all the parameters passed on command line try { output_stream = new java.io.FileOutputStream(output_file_n); output_opened = 1; } catch(java.io.IOException ioe) { System.out.println("Cannot open output file: " + output_file_n + " : Error : " + ioe); output_opened = 0; System.exit(1); } ac = AlacUtils.AlacOpenFileInput(input_file_n); if (ac.error) { System.err.println("Sorry an error has occured"); System.err.println(ac.error_message); System.exit(1); } num_channels = AlacUtils.AlacGetNumChannels(ac); System.out.println("The Apple Lossless file has " + num_channels + " channels"); total_samples = AlacUtils.AlacGetNumSamples(ac); System.out.println("The Apple Lossless file has " + total_samples + " samples"); byteps = AlacUtils.AlacGetBytesPerSample(ac); System.out.println("The Apple Lossless file has " + byteps + " bytes per sample"); sample_rate = AlacUtils.AlacGetSampleRate(ac); bitps = AlacUtils.AlacGetBitsPerSample(ac); /* write wav output headers */ if (write_wav_format != 0) { WavWriter.wavwriter_writeheaders(output_stream, (total_samples * byteps * num_channels), num_channels, sample_rate, byteps, bitps); } /* will convert the entire buffer */ GetBuffer(ac); AlacUtils.AlacCloseFile(ac); if (output_opened != 0) { try { output_stream.close(); } catch(java.io.IOException ioe) { } } } }