#------------------------------------------------------------------------ # # Copyright (c) 1997-1998 by Cornell University. # # See the file "license.txt" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # #------------------------------------------------------------------------ package require DvmBasic package require DvmMpeg if {$argc != 2} { puts "enter input MPEG audio filename : " set infilename [gets stdin] puts "enter PCM output filename : " set outfilename [gets stdin] } else { set infilename [lindex $argv 0] set outfilename [lindex $argv 1] } proc check_bitstream_underflow {bs bp chan size} { set off [bitparser_tell $bp] set left [bitstream_bytes_left $bs $off] if {$left < $size} { bitstream_shift $bs $off bitstream_channel_read $bs $chan $left bitparser_seek $bp 0 } } proc decode_mpeg_audio_l1 {inbs inbp inchan outbs outbp outchan hdr} { set lv [mpeg_audio_syn_data_new] set rv [mpeg_audio_syn_data_new] set left [audio_16_new 384] set right [audio_16_new 384] set merge [audio_16_new 768] set laudio [mpeg_audio_l1_new] set raudio [mpeg_audio_l1_new] set i 0 if {[mpeg_audio_hdr_get_mode $hdr] == "single channel"} { mpeg_audio_l1_mono_parse $inbp $hdr $laudio mpeg_audio_l1_to_audio $hdr $laudio $lv $left set tout [audio_16_cast_to_bitstream $left] bitstream_channel_write_segment $tout $outchan 0 768 } else { mpeg_audio_l1_stereo_parse $inbp $hdr $laudio $raudio mpeg_audio_l1_to_audio $hdr $laudio $lv $left mpeg_audio_l1_to_audio $hdr $raudio $rv $right audio_16_merge $left $right $merge set tout [audio_16_cast_to_bitstream $merge] bitstream_channel_write_segment $tout $outchan 0 1536 } bitstream_free $tout set len [mpeg_audio_hdr_find $inbp] while {![eof $inchan] || $len != -1} { check_bitstream_underflow $inbs $inbp $inchan 2048 mpeg_audio_hdr_parse $inbp $hdr if {[mpeg_audio_hdr_get_mode $hdr] == "single channel"} { mpeg_audio_l1_mono_parse $inbp $hdr $laudio mpeg_audio_l1_to_audio $hdr $laudio $lv $left set tout [audio_16_cast_to_bitstream $left] bitstream_channel_write_segment $tout $outchan 0 768 } else { mpeg_audio_l1_stereo_parse $inbp $hdr $laudio $raudio mpeg_audio_l1_to_audio $hdr $laudio $lv $left mpeg_audio_l1_to_audio $hdr $raudio $rv $right audio_16_merge $left $right $merge set tout [audio_16_cast_to_bitstream $merge] bitstream_channel_write_segment $tout $outchan 0 1536 } bitstream_free $tout set len [mpeg_audio_hdr_find $inbp] } mpeg_audio_l1_free $laudio mpeg_audio_l1_free $raudio audio_free $left audio_free $right audio_free $merge mpeg_audio_hdr_free $hdr mpeg_audio_syn_data_free $lv mpeg_audio_syn_data_free $rv } proc decode_mpeg_audio_l2 {inbs inbp inchan outbs outbp outchan hdr} { set lv [mpeg_audio_syn_data_new] set rv [mpeg_audio_syn_data_new] set left [audio_16_new 1152] set right [audio_16_new 1152] set merge [audio_16_new 2304] set laudio [mpeg_audio_l2_new] set raudio [mpeg_audio_l2_new] set i 0 if {[mpeg_audio_hdr_get_mode $hdr] == "single channel"} { mpeg_audio_l2_mono_parse $inbp $hdr $laudio mpeg_audio_l2_to_audio $hdr $laudio $lv $left set tout [audio_16_cast_to_bitstream $left] bitstream_channel_write_segment $tout $outchan 0 2304 } else { mpeg_audio_l2_stereo_parse $inbp $hdr $laudio $raudio mpeg_audio_l2_to_audio $hdr $laudio $lv $left mpeg_audio_l2_to_audio $hdr $raudio $rv $right audio_16_merge $left $right $merge set tout [audio_16_cast_to_bitstream $merge] bitstream_channel_write_segment $tout $outchan 0 4608 } bitstream_free $tout set len [mpeg_audio_hdr_find $inbp] while {![eof $inchan] || $len != -1} { check_bitstream_underflow $inbs $inbp $inchan 4500 mpeg_audio_hdr_parse $inbp $hdr if {[mpeg_audio_hdr_get_mode $hdr] == "single channel"} { mpeg_audio_l2_mono_parse $inbp $hdr $laudio mpeg_audio_l2_to_audio $hdr $laudio $lv $left set tout [audio_16_cast_to_bitstream $left] bitstream_channel_write_segment $tout $outchan 0 2304 } else { mpeg_audio_l2_stereo_parse $inbp $hdr $laudio $raudio mpeg_audio_l2_to_audio $hdr $laudio $lv $left mpeg_audio_l2_to_audio $hdr $raudio $rv $right audio_16_merge $left $right $merge set tout [audio_16_cast_to_bitstream $merge] bitstream_channel_write_segment $tout $outchan 0 4608 } bitstream_free $tout set len [mpeg_audio_hdr_find $inbp] } mpeg_audio_l2_free $laudio mpeg_audio_l2_free $raudio audio_free $merge audio_free $left audio_free $right mpeg_audio_hdr_free $hdr mpeg_audio_syn_data_free $lv mpeg_audio_syn_data_free $rv } proc decode_mpeg_audio_l3 {inbs inbp inchan outbs outbp outchan hdr} { set lv [mpeg_audio_syn_data_new] set rv [mpeg_audio_syn_data_new] set abs [bitstream_new 4096] set abp [bitparser_new] bitparser_wrap $abp $abs set left [audio_16_new 1152] set right [audio_16_new 1152] set merge [audio_16_new 2304] set granule [mpeg_audio_gra_data_new] set audio [mpeg_audio_l3_new] mpeg_audio_l3_parse $inbp $abp $hdr $audio if {[mpeg_audio_hdr_get_mode $hdr] == "single channel"} { mpeg_audio_l3_mono_to_audio $hdr $audio $lv $rv $granule $left $right set tout [audio_16_cast_to_bitstream $left] bitstream_channel_write_segment $tout $outchan 0 2304 } else { mpeg_audio_l3_stereo_to_audio $hdr $audio $lv $rv $granule $left $right audio_16_merge $left $right $merge set tout [audio_16_cast_to_bitstream $merge] bitstream_channel_write_segment $tout $outchan 0 4608 } bitstream_free $tout set len [mpeg_audio_hdr_find $inbp] set i 0 while {![eof $inchan] || $len != -1} { check_bitstream_underflow $inbs $inbp $inchan 4500 mpeg_audio_hdr_parse $inbp $hdr mpeg_audio_l3_parse $inbp $abp $hdr $audio if {[mpeg_audio_hdr_get_mode $hdr] == "single channel"} { mpeg_audio_l3_mono_to_audio $hdr $audio $lv $rv $granule $left $right set tout [audio_16_cast_to_bitstream $left] bitstream_channel_write_segment $tout $outchan 0 2304 } else { mpeg_audio_l3_stereo_to_audio $hdr $audio $lv $rv $granule $left $right audio_16_merge $left $right $merge set tout [audio_16_cast_to_bitstream $merge] bitstream_channel_write_segment $tout $outchan 0 4608 } bitstream_free $tout set len [mpeg_audio_hdr_find $inbp] } mpeg_audio_l3_free $audio audio_free $left audio_free $right audio_free $merge mpeg_audio_hdr_free $hdr mpeg_audio_syn_data_free $lv mpeg_audio_syn_data_free $rv mpeg_audio_gra_data_free $granule bitstream_free $abs bitparser_free $abp } #----------------------------------------------------------------- # main program #----------------------------------------------------------------- #---------------------------------------------------------------- # open files, create new bitparsers, new bitstreams, read first # 65535 bytes from input file into bitstream and attached the # bitparsers to the bitstreams #---------------------------------------------------------------- set inbp [bitparser_new] set outbp [bitparser_new] set inbs [bitstream_new 65535] set outbs [bitstream_new 65535] set infile [open $infilename r] set outfile [open $outfilename w] fconfigure $infile -translation binary -buffersize 65535 fconfigure $outfile -translation binary -buffersize 65535 bitstream_channel_read $inbs $infile 0 bitparser_wrap $inbp $inbs bitparser_wrap $outbp $outbs #---------------------------------------------------------------- # Allocate and parse the mpeg audio header. Check the layer of # the audio file, and then call the respective routines to decode # the file. #---------------------------------------------------------------- set hdr [mpeg_audio_hdr_new] mpeg_audio_hdr_parse $inbp $hdr set layer [mpeg_audio_hdr_get_layer $hdr] if {$layer == 1} { decode_mpeg_audio_l1 $inbs $inbp $infile $outbs $outbp $outfile $hdr } elseif {$layer == 2} { decode_mpeg_audio_l2 $inbs $inbp $infile $outbs $outbp $outfile $hdr } else { decode_mpeg_audio_l3 $inbs $inbp $infile $outbs $outbp $outfile $hdr } close $infile close $outfile bitstream_free $inbs bitstream_free $outbs bitparser_free $inbp bitparser_free $outbp