; $Id: query_wav.pro,v 1.10 2004/01/21 15:54:59 scottm Exp $ ; ; Copyright (c) 1993-2004, Research Systems, Inc. All rights reserved. ; Unauthorized reproduction prohibited. FUNCTION QUERY_WAV, file, info ;+ ; NAME: ; QUERY_WAV ; ; PURPOSE: ; This function queries information from a Microsoft Windows .WAV ; (RIFF) file ; ; CATEGORY: ; Input/Output ; ; CALLING SEQUENCE: ; Result = QUERY_WAV(File[, info]) ; ; INPUTS: ; File: The full path name of the file to read. ; ; OUTPUTS: ; This function returns 1 if the file can be read as a .WAV file ; and 0 otherwise ; ; OPTIONAL OUTPUTS: ; Info : Anonymous structure containing file information. ; ; KEYWORDS: ; None ; ; SIDE EFFECTS: ; IO is performed. ; ; RESTRICTIONS: ; Only the PCM (uncompressed) data only format is supported. ; ; PROCEDURE: ; Straightforward. Will work on both big endian and little endian ; machines. ; ; EXAMPLE: ; ; MODIFICATION HISTORY: ; RJF, RSI. Sep, 1998. Original version. ; CT, RSI, Aug 2003: Fix bug in error code if unable to open file. ;- ON_IOERROR, bad ON_ERROR, 2 ;Return on error OPENR, unit, file, /GET_LUN, /BLOCK fhdr = { WAVFILEHEADER, $ friff: BYTARR(4), $ ;A four char string fsize: 0L, $ fwave: BYTARR(4) $ ;A four char string } READU, unit, fhdr ;Read the header IF (STRING(fhdr.friff) NE "RIFF") OR $ (STRING(fhdr.fwave) NE "WAVE") THEN BEGIN FREE_LUN, unit RETURN, 0 ENDIF big_endian = (BYTE(1,0,2))[0] EQ 0b chdr = { WAVCHUNKHEADER, $ cid: BYTARR(4), $ csize: 0L $ } cfmt = { WAVFMTCHUNK, $ tag: 0, $ chan: 0, $ rate: 0L, $ bps: 0L, $ balign: 0, $ bits: 0, $ bextra: 0 $ } ; Find the 'fmt ' chunk READU, unit, chdr IF (big_endian) THEN chdr = SWAP_ENDIAN(chdr) WHILE (STRING(chdr.cid) NE 'fmt ') DO BEGIN POINT_LUN, -unit, pos POINT_LUN, unit, pos+chdr.csize READU, unit, chdr IF (big_endian) THEN chdr = SWAP_ENDIAN(chdr) END ; Use the header size to move past fmt chunk in case ; struct size does not match. POINT_LUN, -unit, pos READU, unit, cfmt POINT_LUN, unit, pos+chdr.csize IF (big_endian) THEN cfmt = SWAP_ENDIAN(cfmt) IF (cfmt.tag NE 1) THEN BEGIN FREE_LUN, unit RETURN, 0 END ; Find the 'data' chunk READU, unit, chdr IF (big_endian) THEN chdr = SWAP_ENDIAN(chdr) WHILE (STRING(chdr.cid) NE 'data') DO BEGIN POINT_LUN, -unit, pos POINT_LUN, unit, pos+chdr.csize READU, unit, chdr IF (big_endian) THEN chdr = SWAP_ENDIAN(chdr) END ; info struct info = { $ CHANNELS: cfmt.chan, $ SAMPLES_PER_SEC: cfmt.rate, $ BITS_PER_SAMPLE: cfmt.bits $ } CLOSE, unit FREE_LUN, unit RETURN, 1 bad: if N_ELEMENTS(unit) GT 0 then $ if (unit ne 0) then FREE_LUN, unit RETURN, 0 END