00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <stdio.h>
00036 #include <assert.h>
00037 #include <time.h>
00038
00039 #include "musepack/musepack.h"
00040
00041
00042
00043
00044
00045 typedef struct reader_data_t {
00046 FILE *file;
00047 long size;
00048 BOOL seekable;
00049 } reader_data;
00050
00051
00052
00053
00054 mpc_int32_t
00055 read_impl(void *data, void *ptr, mpc_int32_t size)
00056 {
00057 reader_data *d = (reader_data *) data;
00058 return fread(ptr, 1, size, d->file);
00059 }
00060
00061 BOOL
00062 seek_impl(void *data, mpc_int32_t offset)
00063 {
00064 reader_data *d = (reader_data *) data;
00065 return d->seekable ? !fseek(d->file, offset, SEEK_SET) : false;
00066 }
00067
00068 mpc_int32_t
00069 tell_impl(void *data)
00070 {
00071 reader_data *d = (reader_data *) data;
00072 return ftell(d->file);
00073 }
00074
00075 mpc_int32_t
00076 get_size_impl(void *data)
00077 {
00078 reader_data *d = (reader_data *) data;
00079 return d->size;
00080 }
00081
00082 BOOL
00083 canseek_impl(void *data)
00084 {
00085 reader_data *d = (reader_data *) data;
00086 return d->seekable;
00087 }
00088
00089 #define WFX_SIZE (2+2+4+4+2+2)
00090
00091 #ifdef MPC_FIXED_POINT
00092 static int
00093 shift_signed(MPC_SAMPLE_FORMAT val, int shift)
00094 {
00095 if (shift > 0)
00096 val <<= shift;
00097 else if (shift < 0)
00098 val >>= -shift;
00099 return (int)val;
00100 }
00101 #endif
00102
00103 class WavWriter {
00104 public:
00105 WavWriter(FILE * p_output, unsigned p_nch, unsigned p_bps,
00106 unsigned p_srate)
00107 : m_file(p_output), m_nch(p_nch), m_bps(p_bps), m_srate(p_srate) {
00108 assert(m_bps == 16 || m_bps == 24);
00109
00110 WriteRaw("RIFF", 4);
00111 WriteDword(0);
00112
00113 WriteRaw("WAVE", 4);
00114 WriteRaw("fmt ", 4);
00115 WriteDword(WFX_SIZE);
00116
00117 WriteWord(1);
00118 WriteWord(m_nch);
00119 WriteDword(m_srate);
00120 WriteDword(m_srate * m_nch * (m_bps >> 3));
00121 WriteWord(m_nch * (m_bps >> 3));
00122 WriteWord(m_bps);
00123
00124
00125
00126
00127
00128
00129
00130
00131 WriteRaw("data", 4);
00132 WriteDword(0);
00133
00134 m_data_bytes_written = 0;
00135 } BOOL WriteSamples(const MPC_SAMPLE_FORMAT * p_buffer, unsigned p_size) {
00136 unsigned n;
00137 int clip_min = -1 << (m_bps - 1),
00138 clip_max = (1 << (m_bps - 1)) - 1, float_scale = 1 << (m_bps - 1);
00139 for (n = 0; n < p_size; n++) {
00140 int val;
00141 #ifdef MPC_FIXED_POINT
00142 val =
00143 shift_signed(p_buffer[n],
00144 m_bps - MPC_FIXED_POINT_SCALE_SHIFT);
00145 #else
00146 val = (int)(p_buffer[n] * float_scale);
00147 #endif
00148 if (val < clip_min)
00149 val = clip_min;
00150 else if (val > clip_max)
00151 val = clip_max;
00152 if (!WriteInt(val, m_bps))
00153 return false;
00154 }
00155 m_data_bytes_written += p_size * (m_bps >> 3);
00156 return true;
00157 }
00158
00159 ~WavWriter() {
00160 if (m_data_bytes_written & 1) {
00161 char blah = 0;
00162 WriteRaw(&blah, 1);
00163 m_data_bytes_written++;
00164 }
00165 Seek(4);
00166 WriteDword((unsigned long)(m_data_bytes_written + 4 + 8 + WFX_SIZE +
00167 8));
00168 Seek(8 + 4 + 8 + WFX_SIZE + 4);
00169 WriteDword(m_data_bytes_written);
00170 }
00171
00172 private:
00173
00174 BOOL Seek(unsigned p_offset) {
00175 return !fseek(m_file, p_offset, SEEK_SET);
00176 }
00177
00178 BOOL WriteRaw(const void *p_buffer, unsigned p_bytes) {
00179 return fwrite(p_buffer, 1, p_bytes, m_file) == p_bytes;
00180 }
00181
00182 BOOL WriteDword(unsigned long p_val) {
00183 return WriteInt(p_val, 32);
00184 }
00185 BOOL WriteWord(unsigned short p_val) {
00186 return WriteInt(p_val, 16);
00187 }
00188
00189
00190 BOOL WriteInt(unsigned int p_val, unsigned p_width_bits) {
00191 unsigned char temp;
00192 unsigned shift = 0;
00193 assert((p_width_bits % 8) == 0);
00194 do {
00195 temp = (unsigned char)((p_val >> shift) & 0xFF);
00196 if (!WriteRaw(&temp, 1))
00197 return false;
00198 shift += 8;
00199 } while (shift < p_width_bits);
00200 return true;
00201 }
00202
00203 unsigned m_nch, m_bps, m_srate;
00204 FILE *m_file;
00205 unsigned m_data_bytes_written;
00206 };
00207
00208
00209 static void
00210 usage(const char *exename)
00211 {
00212 printf
00213 ("Usage: %s <infile.mpc> [<outfile.wav>]\nIf <outfile.wav> is not specified, decoder will run in benchmark mode.\n",
00214 exename);
00215 }
00216
00217 int
00218 main(int argc, char **argv)
00219 {
00220 if (argc != 2 && argc != 3) {
00221 if (argc > 0)
00222 usage(argv[0]);
00223 return 0;
00224 }
00225
00226 FILE *input = fopen(argv[1], "rb");
00227 FILE *output = 0;
00228 if (input == 0) {
00229 usage(argv[0]);
00230 printf("Error opening input file: \"%s\"\n", argv[1]);
00231 return 1;
00232 }
00233
00234 if (argc == 3) {
00235 output = fopen(argv[2], "wb");
00236 if (output == 0) {
00237 fclose(input);
00238 usage(argv[0]);
00239 printf("Error opening output file: \"%s\"\n", argv[2]);
00240 return 1;
00241 }
00242 }
00243
00244
00245 reader_data data;
00246 data.file = input;
00247 data.seekable = true;
00248 fseek(data.file, 0, SEEK_END);
00249 data.size = ftell(data.file);
00250 fseek(data.file, 0, SEEK_SET);
00251
00252
00253 mpc_decoder decoder;
00254 mpc_reader reader;
00255 reader.read = read_impl;
00256 reader.seek = seek_impl;
00257 reader.tell = tell_impl;
00258 reader.get_size = get_size_impl;
00259 reader.canseek = canseek_impl;
00260 reader.data = &data;
00261
00262
00263 mpc_streaminfo info;
00264 mpc_streaminfo_init(&info);
00265 if (mpc_streaminfo_read(&info, &reader) != ERROR_CODE_OK) {
00266 printf("Not a valid musepack file: \"%s\"\n", argv[1]);
00267 return 1;
00268 }
00269
00270
00271 mpc_decoder_setup(&decoder, &reader);
00272 if (!mpc_decoder_initialize(&decoder, &info)) {
00273 printf("Error initializing decoder.\n", argv[1]);
00274 return 1;
00275 }
00276
00277
00278 printf("Decoding from:\n%s\nTo:\n%s\n", argv[1],
00279 output ? argv[2] : "N/A");
00280 WavWriter *wavwriter =
00281 output ? new WavWriter(output, 2, 16, info.sample_freq) : 0;
00282 MPC_SAMPLE_FORMAT sample_buffer[MPC_DECODER_BUFFER_LENGTH];
00283 clock_t begin, end;
00284 begin = clock();
00285 unsigned total_samples = 0;
00286 BOOL successful = FALSE;
00287 for (;;) {
00288 unsigned status = mpc_decoder_decode(&decoder, sample_buffer, 0, 0);
00289 if (status == (unsigned)(-1)) {
00290
00291 printf("Error decoding file.\n");
00292 break;
00293 }
00294 else if (status == 0)
00295 {
00296 successful = true;
00297 break;
00298 }
00299 else
00300 {
00301 total_samples += status;
00302 if (wavwriter) {
00303 if (!wavwriter->
00304 WriteSamples(sample_buffer, status * 2)) {
00305 printf("Write error.\n");
00306 break;
00307 }
00308 }
00309 }
00310 }
00311
00312 end = clock();
00313
00314 if (wavwriter) {
00315 delete wavwriter;
00316 }
00317
00318 if (successful) {
00319 printf("\nFinished.\nTotal samples decoded: %u.\n", total_samples);
00320 unsigned ms = (end - begin) * 1000 / CLOCKS_PER_SEC;
00321 unsigned ratio =
00322 (unsigned)((double)total_samples / (double)info.sample_freq /
00323 ((double)ms / 1000.0) * 100.0);
00324 printf("Time: %u ms (%u.%02ux).\n", ms, ratio / 100, ratio % 100);
00325 }
00326
00327 return 0;
00328 }