Update AudioExtractor.java
parent
80760bc534
commit
21efae2c2a
|
@ -38,63 +38,6 @@ public class AudioExtractor {
|
|||
*/
|
||||
private final static boolean CMD_MODE = true;
|
||||
|
||||
/**
|
||||
* ANSI code to go up one line, followed by a carriage return.
|
||||
* Useful for overwriting user input.
|
||||
*/
|
||||
private final static String ANSI_BACKLINE = "\033[F\r";
|
||||
/**
|
||||
* ANSI code to switch to beige colored text.
|
||||
* Useful for highlighting user input.
|
||||
*/
|
||||
private final static String ANSI_BEIGE = "\u001B[93m";
|
||||
|
||||
/**
|
||||
* Hex value for the ASCII sequence "RIFF".
|
||||
* Indicates the start of a RIFF header in WAV files.
|
||||
*/
|
||||
private final static int ASCII_RIFF = 0x5249_4646;
|
||||
/**
|
||||
* Hex value for the ASCII sequence "RIFF".
|
||||
* Indicates the start of a RIFF header in WAV files.
|
||||
*/
|
||||
private final static int ASCII_WAVE = 0x5741_5645;
|
||||
/**
|
||||
* Hex value for the ASCII sequence "fmt ".
|
||||
* Indicates the start of a format chunk in WAV files.
|
||||
*/
|
||||
private final static int ASCII_fmt = 0x666D_7420;
|
||||
/**
|
||||
* Hex value for the ASCII sequence "smpl".
|
||||
* Indicates the start of a sample chunk in WAV files.
|
||||
*/
|
||||
private final static int ASCII_smpl = 0x736D_706C;
|
||||
/**
|
||||
* Hex value for the ASCII sequence "data".
|
||||
* Indicates the start of a data chunk in WAV files.
|
||||
*/
|
||||
private final static int ASCII_data = 0x6461_7461;
|
||||
/**
|
||||
* Hex value for the ASCII sequence "ALIG".
|
||||
* Indicates the start of an alignment chunk in WAV files.
|
||||
*/
|
||||
private final static int ASCII_ALIG = 0x414C_4947;
|
||||
/**
|
||||
* Hex value for the ASCII sequence "x2st".
|
||||
* Indicates the start of an XMA stream chunk in WAV files.
|
||||
*/
|
||||
private final static int ASCII_x2st = 0x7832_7374;
|
||||
/**
|
||||
* Hex value for the ASCII sequence "seek".
|
||||
* Indicates the start of an XMA stream chunk in WAV files.
|
||||
*/
|
||||
private final static int ASCII_seek = 0x7365_656B;
|
||||
/**
|
||||
* Hex value for the ASCII sequence "fLaC".
|
||||
* Indicates the start of an FLAC file.
|
||||
*/
|
||||
private final static int ASCII_fLaC = 0x664C_6143;
|
||||
|
||||
/**
|
||||
* BIN files must first be extracted from game disk to use this program.
|
||||
* By default uses program directory for I/O and saves audio as WAV.<br>
|
||||
|
@ -186,6 +129,9 @@ public class AudioExtractor {
|
|||
}
|
||||
|
||||
case "convert": {
|
||||
// File audioFile = retrieveAudio(reader);
|
||||
// if(audioFile.isFile())
|
||||
// convert(audioFile, encoding);
|
||||
|
||||
}
|
||||
|
||||
|
@ -214,87 +160,83 @@ public class AudioExtractor {
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
System.exit(0);
|
||||
|
||||
if(args.length > 0) {
|
||||
System.out.println("Arguments\t:");
|
||||
for(int i = 0; i < args.length; i++)
|
||||
System.out.print(Ansi.colorize(args[i] + ' ', Attribute.BRIGHT_GREEN_TEXT()));
|
||||
}
|
||||
|
||||
if(args.length > 0) {
|
||||
switch(args[0]) {
|
||||
|
||||
case "help":
|
||||
if(args.length > 1)
|
||||
switch(args[1]) {
|
||||
case "extract":
|
||||
|
||||
break;
|
||||
case "pack":
|
||||
break;
|
||||
case "print":
|
||||
break;
|
||||
}
|
||||
System.out.println("java -jar RR6AudioExtractor.jar [operation] [package] [extract] [option]");
|
||||
break;
|
||||
|
||||
case "extract":
|
||||
// TODO
|
||||
break;
|
||||
|
||||
case "pack":
|
||||
// TODO
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Confirm input/output mode
|
||||
boolean packMode = false;
|
||||
if(args.length > 0)
|
||||
packMode = args[0].equalsIgnoreCase("pack");
|
||||
|
||||
// Confirm package directory, else abort
|
||||
File packDirectory;
|
||||
if(args.length > 1)
|
||||
packDirectory = Path.of(args[1]).toFile();
|
||||
else packDirectory = new File(new File(AudioExtractor.class.getProtectionDomain().getCodeSource().getLocation().toURI()).getParent());
|
||||
if(packMode && !packDirectory.exists() && !packDirectory.mkdir()) {
|
||||
System.out.println("Package output directory " + packDirectory + " does not exist, and could not be created. "
|
||||
+ "Program execution aborted.");
|
||||
System.exit(1);
|
||||
} else if(!packMode && !packDirectory.exists()) {
|
||||
System.out.println("Package input directory " + packDirectory + " does not exist. Program execution aborted.");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// Confirm extract directory, else abort
|
||||
File extractDirectory;
|
||||
if(args.length > 2)
|
||||
extractDirectory = Path.of(args[2]).toFile();
|
||||
else extractDirectory = packDirectory;
|
||||
if(!packMode && !extractDirectory.exists() && !extractDirectory.mkdir()) {
|
||||
System.out.println("Extract output directory " + extractDirectory + " does not exist, and could not be created. "
|
||||
+ "Program execution aborted.");
|
||||
System.exit(2);
|
||||
}
|
||||
|
||||
// Confirm BGM output format
|
||||
boolean compressBGM = false;
|
||||
if(args.length > 3)
|
||||
compressBGM = args[3].equalsIgnoreCase("FLAC");
|
||||
|
||||
// Begin operation
|
||||
if(packMode)
|
||||
pack(packDirectory, extractDirectory);
|
||||
else extract(packDirectory, extractDirectory, compressBGM);
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Examines a given file and reads some of its properties.
|
||||
*
|
||||
* @param givenFile
|
||||
*/
|
||||
public static void identify(File givenFile) {
|
||||
|
||||
// TODO check for characteristics of BIN or WAV files
|
||||
String name = givenFile.getName();
|
||||
System.out.println("Name:\t" + name);
|
||||
|
||||
long size = givenFile.length();
|
||||
System.out.println("Size:\t" + size + " Bytes" + (size > 1024 ? " (" + convertBytes(size) + ")" : "") + "\n");
|
||||
|
||||
// file extension
|
||||
int extIndex = name.lastIndexOf('.');
|
||||
String extension = null;
|
||||
if(extIndex > 0 && extIndex < name.length() - 1)
|
||||
extension = name.substring(extIndex + 1);
|
||||
|
||||
try {
|
||||
RandomAccessFile file = new RandomAccessFile(givenFile, "r");
|
||||
switch(extension.toLowerCase()) {
|
||||
case "bin": {
|
||||
LinkedHashMap<Integer, Integer> tracklist = findAudioTracks(file);
|
||||
System.out.println(tracklist.size() + " Tracks (" + convertBytes(size / tracklist.size()) + " avg size)\n");
|
||||
System.out.println("Format Info");
|
||||
readFormatChunk(file, 0x0C);
|
||||
break;
|
||||
}
|
||||
case "wav":
|
||||
case "xma":
|
||||
default: {
|
||||
for(long i = 0; i < size - 4; i += 4) {
|
||||
file.seek(i);
|
||||
int value = file.readInt();
|
||||
switch(value) {
|
||||
case ASCII_RIFF: {
|
||||
readRIFFChunk(file, (int) i);
|
||||
break;
|
||||
}
|
||||
case ASCII_fmt: {
|
||||
i = readFormatChunk(file, (int) i) - 4;
|
||||
break;
|
||||
}
|
||||
case ASCII_smpl: {
|
||||
i = readSampleChunk(file, (int) i) - 4;
|
||||
break;
|
||||
}
|
||||
case ASCII_data: {
|
||||
i = readDataChunk(file, (int) i) - 4;
|
||||
break;
|
||||
}
|
||||
case ASCII_ALIG: {
|
||||
i = readAlignmentChunk(file, (int) i) - 4;
|
||||
break;
|
||||
}
|
||||
case ASCII_seek: {
|
||||
i = readx2stChunk(file, (int) i) - 4;
|
||||
break;
|
||||
}
|
||||
case ASCII_x2st: {
|
||||
i = readx2stChunk(file, (int) i) - 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.out.println("Could not read file.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts audio tracks from the given package file.
|
||||
|
@ -363,18 +305,6 @@ public class AudioExtractor {
|
|||
System.out.println("Finished.\n");
|
||||
|
||||
}
|
||||
|
||||
public static void printProgressBar(int current, int total) {
|
||||
int done = 50 * current / total;
|
||||
int todo = 50 - done;
|
||||
String doneStr = ""; // String.format("%" + done + "s", '█');
|
||||
for(int i = 0; i < done; i++)
|
||||
doneStr += '█';
|
||||
String todoStr = ""; // String.format("%" + todo + "s", '_');
|
||||
for(int i = 0; i < todo; i++)
|
||||
doneStr += '_';
|
||||
System.out.println(ANSI_BACKLINE + "Progress: |" + doneStr + todoStr + "| (" + current + "/" + total + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts audio files to the extract directory from package files located at the package directory.
|
||||
|
@ -383,6 +313,7 @@ public class AudioExtractor {
|
|||
* @param packDirectory
|
||||
* @param extractDirectory
|
||||
* @param compressBGM
|
||||
* @deprecated delete after adapting FLAC conversion
|
||||
*/
|
||||
public static void extract(File packDirectory, File extractDirectory, boolean compressBGM) {
|
||||
|
||||
|
@ -514,6 +445,168 @@ public class AudioExtractor {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Packs WAV files located at the extract directory into BIN files at the package directory.
|
||||
*
|
||||
* @param packDirectory
|
||||
* @param extractDirectory
|
||||
*/
|
||||
private static void pack(File packDirectory, File extractDirectory) {
|
||||
|
||||
// Identify extracted folders
|
||||
File[] packages = new File(extractDirectory.toString()).listFiles(new FilenameFilter() {
|
||||
public boolean accept(File dir, String name) {
|
||||
return name.toLowerCase().startsWith("pack_") && !name.toLowerCase().endsWith(".bin");
|
||||
}
|
||||
});
|
||||
|
||||
for(int i = 0; i < packages.length; i++)
|
||||
System.out.println(packages[i].getName());
|
||||
|
||||
for(File packDir : packages) {
|
||||
|
||||
// 1. Compile list of WAV files in extracted directories
|
||||
File[] audioTracks = new File(packDir.toString()).listFiles(new FilenameFilter() {
|
||||
public boolean accept(File dir, String name) {
|
||||
return name.toLowerCase().endsWith(".wav");
|
||||
}
|
||||
});
|
||||
|
||||
// 2. Check if pack files already exist in package directory
|
||||
File pack = new File(packDir.getPath() + ".bin");
|
||||
if(pack.exists());
|
||||
|
||||
// 3. If pack file already exists, insert WAV files into existing file.
|
||||
// 4. If pack file doesn't exist, create new file then insert WAV files.
|
||||
|
||||
}
|
||||
|
||||
// Hypothesis 1: Does Ridge Racer 6 use a predetermined address list for reading tracks from package?
|
||||
// Test 1: Try changing the address of a track and see if the game can handle it successfully.
|
||||
|
||||
// Hypothesis 2: Does Ridge Racer 6 loop tracks in their entirety, or do they use loop points defined in the file header?
|
||||
// Test 1: Try editing loop information and see if it affects in-game playback.
|
||||
// Test 2: Try replacing a track with a WAV file without loop data and see if it loops in in-game playback.
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Patches a WAV file by seeking out its data and smpl chunks,
|
||||
* replacing any existing smpl chunk with a new smpl chunk,
|
||||
* setting loop points at the start and end of the data chunk.
|
||||
*
|
||||
* @param waveFile
|
||||
*/
|
||||
private static void patch(File waveFile) {
|
||||
|
||||
try {
|
||||
RandomAccessFile file = new RandomAccessFile(waveFile, "r");
|
||||
|
||||
// Also Find data location
|
||||
int dataAddress = -1;
|
||||
// Check if sample chunk already exists
|
||||
int smplAddress = -1;
|
||||
|
||||
for(int i = 0; i < file.length(); i += 4) {
|
||||
|
||||
file.seek(i);
|
||||
int scan = file.readInt();
|
||||
|
||||
// match "data" chunk header
|
||||
if(scan == ASCII_data)
|
||||
dataAddress = i;
|
||||
// match "smpl" chunk header
|
||||
else if(scan == ASCII_smpl)
|
||||
smplAddress = i;
|
||||
|
||||
// if both chunks already located, stop seeking
|
||||
if(smplAddress > -1 && dataAddress > -1)
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// Determine size of data chunk
|
||||
int dataSize;
|
||||
if(dataAddress > -1)
|
||||
dataSize = readChunkSize(file, dataAddress);
|
||||
else throw new IOException("Data chunk not in file.");
|
||||
|
||||
// Determine size of smpl chunk
|
||||
int smplSize;
|
||||
if(smplAddress > -1)
|
||||
smplSize = readChunkSize(file, smplAddress);
|
||||
// smpl chunk may not already exist
|
||||
|
||||
// Create new sample chunk
|
||||
// Insert 68-byte sample chunk with loop before data chunk
|
||||
|
||||
byte[] smpl = new byte[68];
|
||||
// smpl (0)
|
||||
smpl[0] = 0x73;
|
||||
smpl[1] = 0x6D;
|
||||
smpl[2] = 0x70;
|
||||
smpl[3] = 0x6C;
|
||||
// size (4)
|
||||
smpl[4] = 0x3C;
|
||||
// manufacturer (8)
|
||||
// product (12)
|
||||
// sample period (16)
|
||||
// MIDI unity note (20)
|
||||
smpl[20] = 0x3C;
|
||||
// MIDI pitch fraction (24)
|
||||
// SMPTE Format (28)
|
||||
// SMPTE Offset (32)
|
||||
// Number of Sample Loops (36)
|
||||
smpl[36] = 0x01;
|
||||
// Sample Loops size (40)
|
||||
// loop ID (44)
|
||||
// loop type (48)
|
||||
// data start
|
||||
// loop start (52)
|
||||
// data end
|
||||
// loop end (56)
|
||||
// tuning fraction (60)
|
||||
// play count (64)
|
||||
|
||||
|
||||
// Set loop points to start and end of data chunk
|
||||
// Update the new file size in RIFF header
|
||||
|
||||
} catch(IOException e) {
|
||||
System.out.println("Failed to patch file.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to show current progress.
|
||||
* Should only be used in CMD Mode.
|
||||
*
|
||||
* @param current
|
||||
* @param total
|
||||
*/
|
||||
public static void printProgressBar(int current, int total) {
|
||||
|
||||
int width = 50; // progress bar total width
|
||||
double progress = (double) current / total; // 0 = none, 1 = complete
|
||||
|
||||
int progressWidth = (int) Math.floor(progress * width);
|
||||
double progressRemainder = (progress * width) % 1.0;
|
||||
int x = (int) Math.floor(progressRemainder * 8);
|
||||
char[] c = { ' ', '▏', '▎', '▍', '▌', '▋', '▊', '▉' };
|
||||
|
||||
String bar = "";
|
||||
for(int i = 0; i < width; i++) {
|
||||
if(i < progressWidth)
|
||||
bar += '█';
|
||||
else if(i == progressWidth)
|
||||
bar += c[x];
|
||||
else bar += ' ';
|
||||
}
|
||||
|
||||
System.out.println(ANSI_BACKLINE + "Progress: |" + bar + "| (" + current + "/" + total + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to prompt user to select a package file, or folder containing one or more packages.
|
||||
|
@ -637,84 +730,6 @@ public class AudioExtractor {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Examines a given file and reads some of its properties.
|
||||
*
|
||||
* @param givenFile
|
||||
*/
|
||||
public static void identify(File givenFile) {
|
||||
|
||||
// TODO check for characteristics of BIN or WAV files
|
||||
String name = givenFile.getName();
|
||||
System.out.println("Name:\t" + name);
|
||||
|
||||
long size = givenFile.length();
|
||||
System.out.println("Size:\t" + size + " Bytes" + (size > 1024 ? " (" + convertBytes(size) + ")" : "") + "\n");
|
||||
|
||||
// file extension
|
||||
int extIndex = name.lastIndexOf('.');
|
||||
String extension = null;
|
||||
if(extIndex > 0 && extIndex < name.length() - 1)
|
||||
extension = name.substring(extIndex + 1);
|
||||
|
||||
try {
|
||||
RandomAccessFile file = new RandomAccessFile(givenFile, "r");
|
||||
switch(extension.toLowerCase()) {
|
||||
case "bin": {
|
||||
LinkedHashMap<Integer, Integer> tracklist = findAudioTracks(file);
|
||||
System.out.println(tracklist.size() + " Tracks (" + convertBytes(size / tracklist.size()) + " avg size)\n");
|
||||
System.out.println("Format Info");
|
||||
readFormatChunk(file, 0x0C);
|
||||
break;
|
||||
}
|
||||
case "wav":
|
||||
case "xma":
|
||||
default: {
|
||||
for(long i = 0; i < size - 4; i += 4) {
|
||||
file.seek(i);
|
||||
int value = file.readInt();
|
||||
switch(value) {
|
||||
case ASCII_RIFF: {
|
||||
readRIFFChunk(file, (int) i);
|
||||
break;
|
||||
}
|
||||
case ASCII_fmt: {
|
||||
i = readFormatChunk(file, (int) i) - 4;
|
||||
break;
|
||||
}
|
||||
case ASCII_smpl: {
|
||||
i = readSampleChunk(file, (int) i) - 4;
|
||||
break;
|
||||
}
|
||||
case ASCII_data: {
|
||||
i = readDataChunk(file, (int) i) - 4;
|
||||
break;
|
||||
}
|
||||
case ASCII_ALIG: {
|
||||
i = readAlignmentChunk(file, (int) i) - 4;
|
||||
break;
|
||||
}
|
||||
case ASCII_seek: {
|
||||
i = readx2stChunk(file, (int) i) - 4;
|
||||
break;
|
||||
}
|
||||
case ASCII_x2st: {
|
||||
i = readx2stChunk(file, (int) i) - 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.out.println("Could not read file.");
|
||||
}
|
||||
|
||||
// check if RIFF header
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to read RIFF header information.
|
||||
*
|
||||
|
@ -1046,138 +1061,7 @@ public class AudioExtractor {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Packs WAV files located at the extract directory into BIN files at the package directory.
|
||||
*
|
||||
* @param packDirectory
|
||||
* @param extractDirectory
|
||||
*/
|
||||
private static void pack(File packDirectory, File extractDirectory) {
|
||||
|
||||
// Identify extracted folders
|
||||
File[] packages = new File(extractDirectory.toString()).listFiles(new FilenameFilter() {
|
||||
public boolean accept(File dir, String name) {
|
||||
return name.toLowerCase().startsWith("pack_") && !name.toLowerCase().endsWith(".bin");
|
||||
}
|
||||
});
|
||||
|
||||
for(int i = 0; i < packages.length; i++)
|
||||
System.out.println(packages[i].getName());
|
||||
|
||||
for(File packDir : packages) {
|
||||
|
||||
// 1. Compile list of WAV files in extracted directories
|
||||
File[] audioTracks = new File(packDir.toString()).listFiles(new FilenameFilter() {
|
||||
public boolean accept(File dir, String name) {
|
||||
return name.toLowerCase().endsWith(".wav");
|
||||
}
|
||||
});
|
||||
|
||||
// 2. Check if pack files already exist in package directory
|
||||
File pack = new File(packDir.getPath() + ".bin");
|
||||
if(pack.exists());
|
||||
|
||||
// 3. If pack file already exists, insert WAV files into existing file.
|
||||
// 4. If pack file doesn't exist, create new file then insert WAV files.
|
||||
|
||||
}
|
||||
|
||||
// Hypothesis 1: Does Ridge Racer 6 use a predetermined address list for reading tracks from package?
|
||||
// Test 1: Try changing the address of a track and see if the game can handle it successfully.
|
||||
|
||||
// Hypothesis 2: Does Ridge Racer 6 loop tracks in their entirety, or do they use loop points defined in the file header?
|
||||
// Test 1: Try editing loop information and see if it affects in-game playback.
|
||||
// Test 2: Try replacing a track with a WAV file without loop data and see if it loops in in-game playback.
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Patches a WAV file by seeking out its data and smpl chunks,
|
||||
* replacing any existing smpl chunk with a new smpl chunk,
|
||||
* setting loop points at the start and end of the data chunk.
|
||||
*
|
||||
* @param waveFile
|
||||
*/
|
||||
private static void patch(File waveFile) {
|
||||
|
||||
try {
|
||||
RandomAccessFile file = new RandomAccessFile(waveFile, "r");
|
||||
|
||||
// Also Find data location
|
||||
int dataAddress = -1;
|
||||
// Check if sample chunk already exists
|
||||
int smplAddress = -1;
|
||||
|
||||
for(int i = 0; i < file.length(); i += 4) {
|
||||
|
||||
file.seek(i);
|
||||
int scan = file.readInt();
|
||||
|
||||
// match "data" chunk header
|
||||
if(scan == ASCII_data)
|
||||
dataAddress = i;
|
||||
// match "smpl" chunk header
|
||||
else if(scan == ASCII_smpl)
|
||||
smplAddress = i;
|
||||
|
||||
// if both chunks already located, stop seeking
|
||||
if(smplAddress > -1 && dataAddress > -1)
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// Determine size of data chunk
|
||||
int dataSize;
|
||||
if(dataAddress > -1)
|
||||
dataSize = readChunkSize(file, dataAddress);
|
||||
else throw new IOException("Data chunk not in file.");
|
||||
|
||||
// Determine size of smpl chunk
|
||||
int smplSize;
|
||||
if(smplAddress > -1)
|
||||
smplSize = readChunkSize(file, smplAddress);
|
||||
// smpl chunk may not already exist
|
||||
|
||||
// Create new sample chunk
|
||||
// Insert 68-byte sample chunk with loop before data chunk
|
||||
|
||||
byte[] smpl = new byte[68];
|
||||
// smpl (0)
|
||||
smpl[0] = 0x73;
|
||||
smpl[1] = 0x6D;
|
||||
smpl[2] = 0x70;
|
||||
smpl[3] = 0x6C;
|
||||
// size (4)
|
||||
smpl[4] = 0x3C;
|
||||
// manufacturer (8)
|
||||
// product (12)
|
||||
// sample period (16)
|
||||
// MIDI unity note (20)
|
||||
smpl[20] = 0x3C;
|
||||
// MIDI pitch fraction (24)
|
||||
// SMPTE Format (28)
|
||||
// SMPTE Offset (32)
|
||||
// Number of Sample Loops (36)
|
||||
smpl[36] = 0x01;
|
||||
// Sample Loops size (40)
|
||||
// loop ID (44)
|
||||
// loop type (48)
|
||||
// data start
|
||||
// loop start (52)
|
||||
// data end
|
||||
// loop end (56)
|
||||
// tuning fraction (60)
|
||||
// play count (64)
|
||||
|
||||
|
||||
// Set loop points to start and end of data chunk
|
||||
// Update the new file size in RIFF header
|
||||
|
||||
} catch(IOException e) {
|
||||
System.out.println("Failed to patch file.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to prompt user to select a WAV file.
|
||||
|
@ -2443,4 +2327,63 @@ public class AudioExtractor {
|
|||
return value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ANSI code to go up one line, followed by a carriage return.
|
||||
* Useful for overwriting user input.
|
||||
*/
|
||||
private final static String ANSI_BACKLINE = "\033[F\r";
|
||||
/**
|
||||
* ANSI code to switch to beige colored text.
|
||||
* Useful for highlighting user input.
|
||||
*/
|
||||
private final static String ANSI_BEIGE = "\u001B[93m";
|
||||
|
||||
/**
|
||||
* Hex value for the ASCII sequence "RIFF".
|
||||
* Indicates the start of a RIFF header in WAV files.
|
||||
*/
|
||||
private final static int ASCII_RIFF = 0x5249_4646;
|
||||
/**
|
||||
* Hex value for the ASCII sequence "RIFF".
|
||||
* Indicates the start of a RIFF header in WAV files.
|
||||
*/
|
||||
private final static int ASCII_WAVE = 0x5741_5645;
|
||||
/**
|
||||
* Hex value for the ASCII sequence "fmt ".
|
||||
* Indicates the start of a format chunk in WAV files.
|
||||
*/
|
||||
private final static int ASCII_fmt = 0x666D_7420;
|
||||
/**
|
||||
* Hex value for the ASCII sequence "smpl".
|
||||
* Indicates the start of a sample chunk in WAV files.
|
||||
*/
|
||||
private final static int ASCII_smpl = 0x736D_706C;
|
||||
/**
|
||||
* Hex value for the ASCII sequence "data".
|
||||
* Indicates the start of a data chunk in WAV files.
|
||||
*/
|
||||
private final static int ASCII_data = 0x6461_7461;
|
||||
/**
|
||||
* Hex value for the ASCII sequence "ALIG".
|
||||
* Indicates the start of an alignment chunk in WAV files.
|
||||
*/
|
||||
private final static int ASCII_ALIG = 0x414C_4947;
|
||||
/**
|
||||
* Hex value for the ASCII sequence "x2st".
|
||||
* Indicates the start of an XMA stream chunk in WAV files.
|
||||
*/
|
||||
private final static int ASCII_x2st = 0x7832_7374;
|
||||
/**
|
||||
* Hex value for the ASCII sequence "seek".
|
||||
* Indicates the start of an XMA stream chunk in WAV files.
|
||||
*/
|
||||
private final static int ASCII_seek = 0x7365_656B;
|
||||
/**
|
||||
* Hex value for the ASCII sequence "fLaC".
|
||||
* Indicates the start of an FLAC file.
|
||||
*/
|
||||
private final static int ASCII_fLaC = 0x664C_6143;
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue