I finished the decoder and it can produce wav file output from an mp3. The good news is that is works, the bad news is that its 34 times to slow to play the audio runtime. (I have a core2 duo running at 1.83ghz.)
Since the spec pdf I found is out of date, I had to resort to looking at a couple mp3 decoders source to get the tables and algorithms. As such the python code is very close in form to the originals. I hate when it feels like im just porting code to python, but the exercise did help me understand the mp3 spec more. I plan to refactor alot of the code that was based on others decoders to make it myown and more python friendly.
Time to start cleaning up the code for readability and speed. Maybe there is enough fat to trim to get the decoding fast enough for direct playback.
Here’s some profile data:
Wed Aug 25 23:19:54 2010 stats.dat 5725333 function calls (5724461 primitive calls) in 139.562 CPU seconds Ordered by: cumulative time List reduced from 413 to 20 due to restriction ncalls tottime percall cumtime percall filename:lineno(function) 1 0.000 0.000 139.564 139.564 :1() 1 0.021 0.021 139.564 139.564 {execfile} 1 0.003 0.003 139.543 139.543 ./pyMP3.py:10() 1 0.017 0.017 122.649 122.649 ./pyMP3.py:149(decode) 100 0.832 0.008 61.701 0.617 ./pyMP3.py:587(polyphase_synthesis) 7200 60.602 0.008 60.719 0.008 ./pyMP3.py:609(subBandSynthesis) 100 1.555 0.016 29.090 0.291 ./pyMP3.py:543(hybrid_synthesis) 12800 27.348 0.002 27.535 0.002 ./pyMP3.py:563(inv_mdct) 100 17.204 0.172 23.309 0.233 ./pyMP3.py:205(dequantize_samples) 1 0.000 0.000 16.655 16.655 ./pyMP3.py:78(__init__) 1 8.702 8.702 16.589 16.589 ./bitbfr.py:2(__init__) 4052179 7.888 0.000 7.888 0.000 {ord} 739584 5.587 0.000 5.587 0.000 {pow} 100 0.101 0.001 4.206 0.042 ./pyMP3.py:637(decode_main_info) 400 1.438 0.004 4.034 0.010 ./pyMP3.py:672(decode_main_data_huffman) 65073 1.410 0.000 2.558 0.000 ./pyMP3.py:714(huffman_decoder) 100 1.471 0.015 1.471 0.015 ./pyMP3.py:510(antialias_samples) 295978 1.296 0.000 1.296 0.000 ./bitbfr.py:18(read_bits) 1 0.486 0.486 1.005 1.005 ./pyMP3.py:179(write_wav) 100 0.898 0.009 0.898 0.009 ./pyMP3.py:273(process_stereo) Wed Aug 25 23:19:54 2010 stats.dat 5725333 function calls (5724461 primitive calls) in 139.562 CPU seconds Ordered by: internal time List reduced from 413 to 20 due to restriction ncalls tottime percall cumtime percall filename:lineno(function) 7200 60.602 0.008 60.719 0.008 ./pyMP3.py:609(subBandSynthesis) 12800 27.348 0.002 27.535 0.002 ./pyMP3.py:563(inv_mdct) 100 17.204 0.172 23.309 0.233 ./pyMP3.py:205(dequantize_samples) 1 8.702 8.702 16.589 16.589 ./bitbfr.py:2(__init__) 4052179 7.888 0.000 7.888 0.000 {ord} 739584 5.587 0.000 5.587 0.000 {pow} 100 1.555 0.016 29.090 0.291 ./pyMP3.py:543(hybrid_synthesis) 100 1.471 0.015 1.471 0.015 ./pyMP3.py:510(antialias_samples) 400 1.438 0.004 4.034 0.010 ./pyMP3.py:672(decode_main_data_huffman) 65073 1.410 0.000 2.558 0.000 ./pyMP3.py:714(huffman_decoder) 295978 1.296 0.000 1.296 0.000 ./bitbfr.py:18(read_bits) 100 0.898 0.009 0.898 0.009 ./pyMP3.py:273(process_stereo) 100 0.832 0.008 61.701 0.617 ./pyMP3.py:587(polyphase_synthesis) 100 0.797 0.008 0.797 0.008 ./pyMP3.py:460(reorder_samples) 230400 0.518 0.000 0.518 0.000 {abs} 1 0.486 0.486 1.005 1.005 ./pyMP3.py:179(write_wav) 35205 0.318 0.000 0.318 0.000 {numpy.core.multiarray.zeros} 115213 0.281 0.000 0.281 0.000 {method 'write' of 'file' objects} 115209 0.237 0.000 0.237 0.000 {_struct.pack} 7230 0.150 0.000 0.150 0.000 {method 'extend' of 'list' objects}
Pingback: Decoding MP3 in Python - Hack a Day