197 lines
6.5 KiB
Java
197 lines
6.5 KiB
Java
/**********************************************************************
|
|
* JDump - JSTOR/Harvard Object Validation Environment
|
|
* Copyright 2004-2005 by the President and Fellows of Harvard College
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or (at
|
|
* your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
* USA
|
|
**********************************************************************/
|
|
|
|
import edu.harvard.hul.ois.jhove.*;
|
|
import java.io.*;
|
|
|
|
/**
|
|
* Dump contents of WAVE file in human-readable format.
|
|
*
|
|
* @author Gary McGath
|
|
*
|
|
*/
|
|
public class WDump extends Dump {
|
|
|
|
/* Fixed value for first 4 bytes */
|
|
private static final int[] sigByte =
|
|
{ 0X52, 0X49, 0X46, 0X46 };
|
|
|
|
private static final boolean ENDIAN = false; /* little endian */
|
|
|
|
/******************************************************************
|
|
* MAIN ENTRY POINT.
|
|
******************************************************************/
|
|
|
|
/**
|
|
* Main entry point.
|
|
* @param args Command line arguments
|
|
*/
|
|
public static void main (String [] args)
|
|
{
|
|
if (args.length < 1) {
|
|
System.err.println ("usage: java WDump file");
|
|
System.exit (-1);
|
|
}
|
|
try {
|
|
FileInputStream file = new FileInputStream (args[0]);
|
|
BufferedInputStream buffer = new BufferedInputStream (file);
|
|
DataInputStream stream = new DataInputStream (buffer);
|
|
ADump dump = new ADump (); // Just to access contained classes
|
|
long os = 0;
|
|
for (int i=0; i<4; i++) {
|
|
int ch;
|
|
ch = stream.readUnsignedByte();
|
|
if (ch != sigByte[i]) {
|
|
System.out.println ("No AIFF FORM header");
|
|
System.exit (-2);
|
|
}
|
|
os++;
|
|
}
|
|
long ckSize = ModuleBase.readUnsignedInt (stream, ENDIAN);
|
|
os += 4;
|
|
|
|
// Read the file type
|
|
String formType = read4Chars (stream);
|
|
os += 4;
|
|
|
|
System.out.println ("00000000: RIFF " + ckSize + ": " + formType);
|
|
|
|
boolean endOfFile = false;
|
|
while (!endOfFile) {
|
|
// Read chunks
|
|
try {
|
|
// Read chunk name.
|
|
String ckID = read4Chars (stream);
|
|
// Read size (excluding chunk name and size fields)
|
|
ckSize = ModuleBase.readUnsignedInt (stream, ENDIAN);
|
|
System.out.print (leading (os, 8) + os + ": " + ckID +
|
|
" " + ckSize);
|
|
long alreadyRead = 0;
|
|
if (ckID.equals ("fact")) {
|
|
long sampleLength =
|
|
ModuleBase.readUnsignedInt (stream, ENDIAN);
|
|
System.out.print (": " + sampleLength);
|
|
alreadyRead = 4;
|
|
}
|
|
else if (ckID.equals ("fmt ")) {
|
|
int formatTag = ModuleBase.readUnsignedShort (stream,
|
|
ENDIAN);
|
|
int channels = ModuleBase.readUnsignedShort (stream,
|
|
ENDIAN);
|
|
long samplesPerSec =
|
|
ModuleBase.readUnsignedInt (stream, ENDIAN);
|
|
long avgBytesPerSec =
|
|
ModuleBase.readUnsignedInt (stream, ENDIAN);
|
|
int blockAlign = ModuleBase.readUnsignedShort (stream,
|
|
ENDIAN);
|
|
String hex = Integer.toHexString (formatTag);
|
|
System.out.print (": 0x" + leading (hex, 4) + hex +
|
|
" " + channels + " " +
|
|
samplesPerSec + " " +
|
|
avgBytesPerSec + " " + blockAlign);
|
|
alreadyRead = 14;
|
|
if (ckSize > 14) {
|
|
int bitsPerSample =
|
|
ModuleBase.readUnsignedShort (stream, ENDIAN);
|
|
System.out.print (" " + bitsPerSample);
|
|
alreadyRead = 16;
|
|
if (ckSize > 16) {
|
|
int size =
|
|
ModuleBase.readUnsignedShort (stream,
|
|
ENDIAN);
|
|
System.out.print (" " + size);
|
|
alreadyRead = 18;
|
|
if (size == 22) {
|
|
int validBitsPerSample =
|
|
ModuleBase.readUnsignedShort (stream,
|
|
ENDIAN);
|
|
long channelMask =
|
|
ModuleBase.readUnsignedInt (stream,
|
|
ENDIAN);
|
|
hex = Long.toHexString (channelMask);
|
|
System.out.print (" " +
|
|
validBitsPerSample +
|
|
" 0x" +
|
|
leading (hex, 8) + hex +
|
|
" 0x");
|
|
for (int i=0; i<4; i++) {
|
|
long guid =
|
|
ModuleBase.readUnsignedInt (
|
|
stream,
|
|
ENDIAN);
|
|
hex = Long.toHexString (guid);
|
|
System.out.print (leading (hex, 8) +
|
|
hex);
|
|
}
|
|
alreadyRead = 40;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
System.out.println ();
|
|
|
|
if (ckID.equals ("list") || ckID.equals ("LIST")) {
|
|
readNestedChunks (ckID, stream, ckSize, os + 8);
|
|
}
|
|
else {
|
|
stream.skipBytes ((int) (ckSize - alreadyRead));
|
|
}
|
|
os += ckSize + 8;
|
|
}
|
|
catch (EOFException e) {
|
|
endOfFile = true;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
}
|
|
}
|
|
|
|
/* The "list" and "LIST" chunks (which are two distinct chunk types)
|
|
hold nested chunks. */
|
|
private static void readNestedChunks
|
|
(String ckID, DataInputStream stream, long ckSize, long os)
|
|
throws IOException
|
|
{
|
|
String listType = read4Chars (stream);
|
|
System.out.println ("List type = " + listType);
|
|
while (ckSize > 0) {
|
|
String subCkID = read4Chars (stream);
|
|
long subCkSize = ModuleBase.readUnsignedInt (stream, ENDIAN, null);
|
|
System.out.println (leading (os, 8) + os + ": " +
|
|
ckID + "/" + subCkID + " " + subCkSize);
|
|
stream.skipBytes ((int) subCkSize);
|
|
os += subCkSize + 8;
|
|
ckSize -= subCkSize + 8;
|
|
}
|
|
}
|
|
|
|
private static String read4Chars (DataInputStream stream)
|
|
throws IOException
|
|
{
|
|
StringBuffer sbuf = new StringBuffer(4);
|
|
for (int i = 0; i < 4; i++) {
|
|
int ch = ModuleBase.readUnsignedByte(stream, null);
|
|
sbuf.append((char) ch);
|
|
}
|
|
return sbuf.toString ();
|
|
}
|
|
}
|