#------------------------------------------------------------------------
#
# 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