343 lines
18 KiB
HTML
Executable File
343 lines
18 KiB
HTML
Executable File
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
|
|
<title>libmusepack: src/sample.cpp Source File</title>
|
|
<link href="custom.css" rel="stylesheet" type="text/css">
|
|
</head><body>
|
|
<!-- Generated by Doxygen 1.4.1 -->
|
|
<div class="qindex"><a class="qindex" href="index.html">Main Page</a> | <a class="qindex" href="annotated.html">Class List</a> | <a class="qindex" href="dirs.html">Directories</a> | <a class="qindex" href="files.html">File List</a> | <a class="qindex" href="globals.html">File Members</a> | <a class="qindex" href="pages.html">Related Pages</a></div>
|
|
<div class="nav">
|
|
<a class="el" href="dir_000002.html">src</a></div>
|
|
<h1>sample.cpp</h1><div class="fragment"><pre class="fragment">00001 <span class="comment">/*</span>
|
|
00002 <span class="comment"> Copyright (c) 2005, The Musepack Development Team</span>
|
|
00003 <span class="comment"> All rights reserved.</span>
|
|
00004 <span class="comment"></span>
|
|
00005 <span class="comment"> Redistribution and use in source and binary forms, with or without</span>
|
|
00006 <span class="comment"> modification, are permitted provided that the following conditions are</span>
|
|
00007 <span class="comment"> met:</span>
|
|
00008 <span class="comment"></span>
|
|
00009 <span class="comment"> * Redistributions of source code must retain the above copyright</span>
|
|
00010 <span class="comment"> notice, this list of conditions and the following disclaimer.</span>
|
|
00011 <span class="comment"></span>
|
|
00012 <span class="comment"> * Redistributions in binary form must reproduce the above</span>
|
|
00013 <span class="comment"> copyright notice, this list of conditions and the following</span>
|
|
00014 <span class="comment"> disclaimer in the documentation and/or other materials provided</span>
|
|
00015 <span class="comment"> with the distribution.</span>
|
|
00016 <span class="comment"></span>
|
|
00017 <span class="comment"> * Neither the name of the The Musepack Development Team nor the</span>
|
|
00018 <span class="comment"> names of its contributors may be used to endorse or promote</span>
|
|
00019 <span class="comment"> products derived from this software without specific prior</span>
|
|
00020 <span class="comment"> written permission.</span>
|
|
00021 <span class="comment"></span>
|
|
00022 <span class="comment"> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS</span>
|
|
00023 <span class="comment"> "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT</span>
|
|
00024 <span class="comment"> LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR</span>
|
|
00025 <span class="comment"> A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT</span>
|
|
00026 <span class="comment"> OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,</span>
|
|
00027 <span class="comment"> SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT</span>
|
|
00028 <span class="comment"> LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,</span>
|
|
00029 <span class="comment"> DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY</span>
|
|
00030 <span class="comment"> THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT</span>
|
|
00031 <span class="comment"> (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE</span>
|
|
00032 <span class="comment"> OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span>
|
|
00033 <span class="comment">*/</span>
|
|
00034
|
|
00035 <span class="preprocessor">#include <stdio.h></span>
|
|
00036 <span class="preprocessor">#include <assert.h></span>
|
|
00037 <span class="preprocessor">#include <time.h></span>
|
|
00038
|
|
00039 <span class="preprocessor">#include "<a class="code" href="musepack_8h.html">musepack/musepack.h</a>"</span>
|
|
00040
|
|
00041 <span class="comment">/*</span>
|
|
00042 <span class="comment"> The data bundle we pass around with our reader to store file</span>
|
|
00043 <span class="comment"> position and size etc. </span>
|
|
00044 <span class="comment">*/</span>
|
|
00045 <span class="keyword">typedef</span> <span class="keyword">struct </span>reader_data_t {
|
|
00046 FILE *file;
|
|
00047 <span class="keywordtype">long</span> size;
|
|
00048 BOOL seekable;
|
|
00049 } reader_data;
|
|
00050
|
|
00051 <span class="comment">/*</span>
|
|
00052 <span class="comment"> Our implementations of the mpc_reader callback functions.</span>
|
|
00053 <span class="comment">*/</span>
|
|
00054 mpc_int32_t
|
|
00055 read_impl(<span class="keywordtype">void</span> *data, <span class="keywordtype">void</span> *ptr, mpc_int32_t size)
|
|
00056 {
|
|
00057 reader_data *d = (reader_data *) data;
|
|
00058 <span class="keywordflow">return</span> fread(ptr, 1, size, d->file);
|
|
00059 }
|
|
00060
|
|
00061 BOOL
|
|
00062 seek_impl(<span class="keywordtype">void</span> *data, mpc_int32_t offset)
|
|
00063 {
|
|
00064 reader_data *d = (reader_data *) data;
|
|
00065 <span class="keywordflow">return</span> d->seekable ? !fseek(d->file, offset, SEEK_SET) : false;
|
|
00066 }
|
|
00067
|
|
00068 mpc_int32_t
|
|
00069 tell_impl(<span class="keywordtype">void</span> *data)
|
|
00070 {
|
|
00071 reader_data *d = (reader_data *) data;
|
|
00072 <span class="keywordflow">return</span> ftell(d->file);
|
|
00073 }
|
|
00074
|
|
00075 mpc_int32_t
|
|
00076 get_size_impl(<span class="keywordtype">void</span> *data)
|
|
00077 {
|
|
00078 reader_data *d = (reader_data *) data;
|
|
00079 <span class="keywordflow">return</span> d->size;
|
|
00080 }
|
|
00081
|
|
00082 BOOL
|
|
00083 canseek_impl(<span class="keywordtype">void</span> *data)
|
|
00084 {
|
|
00085 reader_data *d = (reader_data *) data;
|
|
00086 <span class="keywordflow">return</span> d->seekable;
|
|
00087 }
|
|
00088
|
|
00089 <span class="preprocessor">#define WFX_SIZE (2+2+4+4+2+2)</span>
|
|
00090 <span class="preprocessor"></span>
|
|
00091 <span class="preprocessor">#ifdef MPC_FIXED_POINT</span>
|
|
00092 <span class="preprocessor"></span><span class="keyword">static</span> <span class="keywordtype">int</span>
|
|
00093 shift_signed(MPC_SAMPLE_FORMAT val, <span class="keywordtype">int</span> shift)
|
|
00094 {
|
|
00095 <span class="keywordflow">if</span> (shift > 0)
|
|
00096 val <<= shift;
|
|
00097 else if (shift < 0)
|
|
00098 val >>= -shift;
|
|
00099 return (<span class="keywordtype">int</span>)val;
|
|
00100 }
|
|
00101 #endif
|
|
00102
|
|
00103 class WavWriter {
|
|
00104 <span class="keyword">public</span>:
|
|
00105 WavWriter(FILE * p_output, <span class="keywordtype">unsigned</span> p_nch, <span class="keywordtype">unsigned</span> p_bps,
|
|
00106 <span class="keywordtype">unsigned</span> 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(<span class="stringliteral">"RIFF"</span>, 4);
|
|
00111 WriteDword(0); <span class="comment">//fix this in destructor</span>
|
|
00112
|
|
00113 WriteRaw(<span class="stringliteral">"WAVE"</span>, 4);
|
|
00114 WriteRaw(<span class="stringliteral">"fmt "</span>, 4);
|
|
00115 WriteDword(WFX_SIZE);
|
|
00116
|
|
00117 WriteWord(1); <span class="comment">//WAVE_FORMAT_PCM</span>
|
|
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 <span class="comment">/*</span>
|
|
00124 <span class="comment"> WORD wFormatTag; </span>
|
|
00125 <span class="comment"> WORD nChannels; </span>
|
|
00126 <span class="comment"> DWORD nSamplesPerSec; </span>
|
|
00127 <span class="comment"> DWORD nAvgBytesPerSec; </span>
|
|
00128 <span class="comment"> WORD nBlockAlign; </span>
|
|
00129 <span class="comment"> WORD wBitsPerSample; </span>
|
|
00130 <span class="comment"> */</span>
|
|
00131 WriteRaw(<span class="stringliteral">"data"</span>, 4);
|
|
00132 WriteDword(0); <span class="comment">//fix this in destructor</span>
|
|
00133
|
|
00134 m_data_bytes_written = 0;
|
|
00135 } BOOL WriteSamples(<span class="keyword">const</span> MPC_SAMPLE_FORMAT * p_buffer, <span class="keywordtype">unsigned</span> p_size) {
|
|
00136 <span class="keywordtype">unsigned</span> n;
|
|
00137 <span class="keywordtype">int</span> clip_min = -1 << (m_bps - 1),
|
|
00138 clip_max = (1 << (m_bps - 1)) - 1, float_scale = 1 << (m_bps - 1);
|
|
00139 <span class="keywordflow">for</span> (n = 0; n < p_size; n++) {
|
|
00140 <span class="keywordtype">int</span> val;
|
|
00141 <span class="preprocessor">#ifdef MPC_FIXED_POINT</span>
|
|
00142 <span class="preprocessor"></span> val =
|
|
00143 shift_signed(p_buffer[n],
|
|
00144 m_bps - MPC_FIXED_POINT_SCALE_SHIFT);
|
|
00145 <span class="preprocessor">#else</span>
|
|
00146 <span class="preprocessor"></span> val = (int)(p_buffer[n] * float_scale);
|
|
00147 <span class="preprocessor">#endif</span>
|
|
00148 <span class="preprocessor"></span> <span class="keywordflow">if</span> (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 <span class="keywordflow">if</span> (m_data_bytes_written & 1) {
|
|
00161 <span class="keywordtype">char</span> blah = 0;
|
|
00162 WriteRaw(&blah, 1);
|
|
00163 m_data_bytes_written++;
|
|
00164 }
|
|
00165 Seek(4);
|
|
00166 WriteDword((<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span>)(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 <span class="keyword">private</span>:
|
|
00173
|
|
00174 BOOL Seek(<span class="keywordtype">unsigned</span> p_offset) {
|
|
00175 <span class="keywordflow">return</span> !fseek(m_file, p_offset, SEEK_SET);
|
|
00176 }
|
|
00177
|
|
00178 BOOL WriteRaw(<span class="keyword">const</span> <span class="keywordtype">void</span> *p_buffer, <span class="keywordtype">unsigned</span> p_bytes) {
|
|
00179 <span class="keywordflow">return</span> fwrite(p_buffer, 1, p_bytes, m_file) == p_bytes;
|
|
00180 }
|
|
00181
|
|
00182 BOOL WriteDword(<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> p_val) {
|
|
00183 <span class="keywordflow">return</span> WriteInt(p_val, 32);
|
|
00184 }
|
|
00185 BOOL WriteWord(<span class="keywordtype">unsigned</span> <span class="keywordtype">short</span> p_val) {
|
|
00186 <span class="keywordflow">return</span> WriteInt(p_val, 16);
|
|
00187 }
|
|
00188
|
|
00189 <span class="comment">// write a little-endian number properly</span>
|
|
00190 BOOL WriteInt(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> p_val, <span class="keywordtype">unsigned</span> p_width_bits) {
|
|
00191 <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> temp;
|
|
00192 <span class="keywordtype">unsigned</span> shift = 0;
|
|
00193 assert((p_width_bits % 8) == 0);
|
|
00194 <span class="keywordflow">do</span> {
|
|
00195 temp = (<span class="keywordtype">unsigned</span> char)((p_val >> shift) & 0xFF);
|
|
00196 <span class="keywordflow">if</span> (!WriteRaw(&temp, 1))
|
|
00197 return false;
|
|
00198 shift += 8;
|
|
00199 } while (shift < p_width_bits);
|
|
00200 return true;
|
|
00201 }
|
|
00202
|
|
00203 <span class="keywordtype">unsigned</span> m_nch, m_bps, m_srate;
|
|
00204 FILE *m_file;
|
|
00205 <span class="keywordtype">unsigned</span> m_data_bytes_written;
|
|
00206 };
|
|
00207
|
|
00208
|
|
00209 static <span class="keywordtype">void</span>
|
|
00210 usage(const <span class="keywordtype">char</span> *exename)
|
|
00211 {
|
|
00212 printf
|
|
00213 (<span class="stringliteral">"Usage: %s <infile.mpc> [<outfile.wav>]\nIf <outfile.wav> is not specified, decoder will run in benchmark mode.\n"</span>,
|
|
00214 exename);
|
|
00215 }
|
|
00216
|
|
00217 <span class="keywordtype">int</span>
|
|
00218 main(<span class="keywordtype">int</span> argc, <span class="keywordtype">char</span> **argv)
|
|
00219 {
|
|
00220 <span class="keywordflow">if</span> (argc != 2 && argc != 3) {
|
|
00221 <span class="keywordflow">if</span> (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(<span class="stringliteral">"Error opening input file: \"%s\"\n"</span>, argv[1]);
|
|
00231 <span class="keywordflow">return</span> 1;
|
|
00232 }
|
|
00233
|
|
00234 <span class="keywordflow">if</span> (argc == 3) {
|
|
00235 output = fopen(argv[2], <span class="stringliteral">"wb"</span>);
|
|
00236 <span class="keywordflow">if</span> (output == 0) {
|
|
00237 fclose(input);
|
|
00238 usage(argv[0]);
|
|
00239 printf(<span class="stringliteral">"Error opening output file: \"%s\"\n"</span>, argv[2]);
|
|
00240 <span class="keywordflow">return</span> 1;
|
|
00241 }
|
|
00242 }
|
|
00243
|
|
00244 <span class="comment">/* initialize our reader_data tag the reader will carry around with it */</span>
|
|
00245 reader_data data;
|
|
00246 data.file = input;
|
|
00247 data.seekable = <span class="keyword">true</span>;
|
|
00248 fseek(data.file, 0, SEEK_END);
|
|
00249 data.size = ftell(data.file);
|
|
00250 fseek(data.file, 0, SEEK_SET);
|
|
00251
|
|
00252 <span class="comment">/* set up an mpc_reader linked to our function implementations */</span>
|
|
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 <span class="comment">/* read file's streaminfo data */</span>
|
|
00263 mpc_streaminfo info;
|
|
00264 <a class="code" href="musepack_8h.html#a9">mpc_streaminfo_init</a>(&info);
|
|
00265 <span class="keywordflow">if</span> (<a class="code" href="musepack_8h.html#a10">mpc_streaminfo_read</a>(&info, &reader) != ERROR_CODE_OK) {
|
|
00266 printf(<span class="stringliteral">"Not a valid musepack file: \"%s\"\n"</span>, argv[1]);
|
|
00267 <span class="keywordflow">return</span> 1;
|
|
00268 }
|
|
00269
|
|
00270 <span class="comment">/* instantiate a decoder with our file reader */</span>
|
|
00271 <a class="code" href="musepack_8h.html#a13">mpc_decoder_setup</a>(&decoder, &reader);
|
|
00272 <span class="keywordflow">if</span> (!<a class="code" href="musepack_8h.html#a14">mpc_decoder_initialize</a>(&decoder, &info)) {
|
|
00273 printf(<span class="stringliteral">"Error initializing decoder.\n"</span>, argv[1]);
|
|
00274 <span class="keywordflow">return</span> 1;
|
|
00275 }
|
|
00276
|
|
00277 <span class="comment">/* decode the file */</span>
|
|
00278 printf(<span class="stringliteral">"Decoding from:\n%s\nTo:\n%s\n"</span>, argv[1],
|
|
00279 output ? argv[2] : <span class="stringliteral">"N/A"</span>);
|
|
00280 WavWriter *wavwriter =
|
|
00281 output ? <span class="keyword">new</span> WavWriter(output, 2, 16, info.sample_freq) : 0;
|
|
00282 MPC_SAMPLE_FORMAT sample_buffer[<a class="code" href="musepack_8h.html#a19a8">MPC_DECODER_BUFFER_LENGTH</a>];
|
|
00283 clock_t begin, end;
|
|
00284 begin = clock();
|
|
00285 <span class="keywordtype">unsigned</span> total_samples = 0;
|
|
00286 BOOL successful = FALSE;
|
|
00287 <span class="keywordflow">for</span> (;;) {
|
|
00288 <span class="keywordtype">unsigned</span> status = <a class="code" href="musepack_8h.html#a16">mpc_decoder_decode</a>(&decoder, sample_buffer, 0, 0);
|
|
00289 <span class="keywordflow">if</span> (status == (<span class="keywordtype">unsigned</span>)(-1)) {
|
|
00290 <span class="comment">//decode error</span>
|
|
00291 printf(<span class="stringliteral">"Error decoding file.\n"</span>);
|
|
00292 <span class="keywordflow">break</span>;
|
|
00293 }
|
|
00294 <span class="keywordflow">else</span> <span class="keywordflow">if</span> (status == 0) <span class="comment">//EOF</span>
|
|
00295 {
|
|
00296 successful = <span class="keyword">true</span>;
|
|
00297 <span class="keywordflow">break</span>;
|
|
00298 }
|
|
00299 <span class="keywordflow">else</span> <span class="comment">//status>0</span>
|
|
00300 {
|
|
00301 total_samples += status;
|
|
00302 <span class="keywordflow">if</span> (wavwriter) {
|
|
00303 <span class="keywordflow">if</span> (!wavwriter->
|
|
00304 WriteSamples(sample_buffer, status * <span class="comment">/* stereo */</span> 2)) {
|
|
00305 printf(<span class="stringliteral">"Write error.\n"</span>);
|
|
00306 <span class="keywordflow">break</span>;
|
|
00307 }
|
|
00308 }
|
|
00309 }
|
|
00310 }
|
|
00311
|
|
00312 end = clock();
|
|
00313
|
|
00314 <span class="keywordflow">if</span> (wavwriter) {
|
|
00315 <span class="keyword">delete</span> wavwriter;
|
|
00316 }
|
|
00317
|
|
00318 <span class="keywordflow">if</span> (successful) {
|
|
00319 printf(<span class="stringliteral">"\nFinished.\nTotal samples decoded: %u.\n"</span>, total_samples);
|
|
00320 <span class="keywordtype">unsigned</span> ms = (end - begin) * 1000 / CLOCKS_PER_SEC;
|
|
00321 <span class="keywordtype">unsigned</span> ratio =
|
|
00322 (unsigned)((double)total_samples / (double)info.sample_freq /
|
|
00323 ((double)ms / 1000.0) * 100.0);
|
|
00324 printf(<span class="stringliteral">"Time: %u ms (%u.%02ux).\n"</span>, ms, ratio / 100, ratio % 100);
|
|
00325 }
|
|
00326
|
|
00327 <span class="keywordflow">return</span> 0;
|
|
00328 }
|
|
</pre></div><hr size="1"><address style="align: right;"><small>Generated on Sat Jan 22 09:34:07 2005 for libmusepack by
|
|
<a href="http://www.doxygen.org/index.html">
|
|
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.4.1 </small></address>
|
|
</body>
|
|
</html>
|