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

# Read a WAV file
# input : name - file name to be read from
# output : [list $hdr $audio $inbs]
#          hdr - Wave header parsed from the file
#          audio - audio buffer read from the file
#          inbs - bitstream of the file, should free when
#                 audio is freed

proc read_wave {name} {
    ## open Tcl Channel
    set inf [open $name r]
    fconfigure $inf -translation binary -buffersize 65536

    ## Read the WaveHeader chunk
    # initialize bitstream and bitparser
    set inbs  [bitstream_new 100]
    set inbp  [bitparser_new]
    bitparser_wrap $inbp $inbs

    # read wave file into bitstream
    bitstream_channel_read $inbs $inf 0

    # parse the header
    set hdr   [wave_hdr_new]
    wave_hdr_parse $inbp $hdr

    set res [wave_hdr_get_bits_per_sample $hdr]
    set bytes [wave_hdr_get_data_len $hdr]
    set samples [expr $bytes * 8 / $res]
    set offset [bitparser_tell $inbp]

    ## Read the actual Audio Data
    # Shift the bitstream so that no more header chunk in it
    bitstream_shift $inbs $offset

    # Resize the bitstream to the length of audio data
    bitstream_resize $inbs $bytes
    bitparser_wrap $inbp $inbs
    bitparser_seek $inbp 0

    # Read the rest of the file into bitstream
    set left [bitstream_bytes_left $inbs 0]
    bitstream_channel_read $inbs $inf $left

    ## cast bitstream to audio 
    if {$res == 8} {
        set audio [bitstream_cast_to_audio_8 $inbs 0 $samples]
    } elseif {$res == 16} {
        set audio [bitstream_cast_to_audio_16 $inbs 0 $samples]
    }

    close $inf
    bitparser_free $inbp
    return [list $hdr $audio $inbs]
}

# Write a WAV file
# input : hdr - Wave header to be encoded
#         audio - audio buffer to be written
#         name - file name to be written
# output : none

proc write_wave {hdr audio name} {
    ## Write WAV header
    # Open Tcl Channel
    set outf [open $name w]
    fconfigure $outf -translation binary -buffersize 65536

    # initialize bitstream and bitparser for WAV header output
    set outhdrbs [bitstream_new 100]
    set outhdrbp [bitparser_new]
    bitparser_wrap $outhdrbp $outhdrbs

    # Encode WAV header thru bitparser
    wave_hdr_encode $hdr $outhdrbp

    # Write the WAV header to bitstream
    set hdrlen [bitparser_tell $outhdrbp]
    bitstream_channel_write_segment $outhdrbs $outf 0 $hdrlen

    ## Write the actual Audio Buffer
    set res [wave_hdr_get_bits_per_sample $hdr]

    # Cast the Audio Buffer to bitstream
    if {$res == 8} {
        set outbs [audio_8_cast_to_bitstream $audio]
    } elseif {$res == 16} {
        set outbs [audio_16_cast_to_bitstream $audio]
    }

    # Write the bitstream to Channel
    bitstream_channel_write $outbs $outf 0

    ### Wrap up
    close $outf
    bitparser_free $outhdrbp
    bitstream_free $outhdrbs
}