Last active
January 25, 2024 20:26
-
-
Save Slooowpoke/cf7c799398ee6645c0be16d3f3b23ab2 to your computer and use it in GitHub Desktop.
Convert .wav to .pcm (a little class to remove a .wav header from a file an create a .pcm)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.File; | |
import java.io.FileInputStream; | |
import java.io.FileOutputStream; | |
import java.io.IOException; | |
/** | |
* Creates a PCM file from a Wave (.wav) file | |
*/ | |
public class WaveToPulseCodeModulation { | |
private File inputFile, outputFile; | |
private final int FAILED_SEARCH_INDEX = -99; | |
public WaveToPulseCodeModulation(String inputFile, String outputFile) throws IOException { | |
this.inputFile = new File(inputFile + ".wav"); | |
this.outputFile = new File(outputFile + ".pcm"); | |
// Create an empty output file | |
this.outputFile.createNewFile(); | |
} | |
/** | |
* Converts a PCM to a WAVE by removing the Wave header | |
* First it needs to search for the start of the PCM | |
* The byte sequence marking the start of a PCM in a WAVE file is: | |
* (64 61 74 61) = "data" | |
* | |
* We search for the sequence and then create a file by skipping file reading in the input file | |
* | |
* @return boolean | |
* @throws IOException | |
*/ | |
public boolean convert() throws IOException { | |
// Stream in a byte array and look for a specific sequence | |
// Convert byte to int results in 64 = 100, 61 = 97, 74 = 116, 61= 97 | |
int[] sequence = new int[]{100, 97, 116, 97}; | |
// Generate an input stream | |
FileInputStream is = new FileInputStream(inputFile); | |
// Generate an output stream | |
FileOutputStream outputStream = new FileOutputStream(outputFile.getPath()); | |
byte buffer[] = new byte[1024]; | |
int read = 0; | |
int totalMatched = 0; | |
int indexToSkipHeader = 0; | |
while ((read = is.read(buffer)) > 0) { | |
indexToSkipHeader = findIndexOfSequenceInByteArray(sequence, buffer); | |
// If the index fails, keep searching | |
if(indexToSkipHeader == FAILED_SEARCH_INDEX){ | |
continue; | |
}else{ | |
break; | |
} | |
} | |
// Close the input stream and re-open it | |
is.close(); | |
is = new FileInputStream(inputFile); | |
// Reset out reading variables | |
read = 0; | |
// Now use the indexToSkipHeader to skip a certain amount of bytes when reading it back out | |
is.skip(indexToSkipHeader); | |
while ((read = is.read(buffer)) > 0) { | |
outputStream.write(buffer); | |
} | |
System.out.println("Finished writing file"); | |
return false; | |
} | |
/** | |
* Searches for the index of our sequence | |
* Returns the index of the sequence (total bytes to skip) or returns the failed index | |
* | |
* @param int[] sequence | |
* @param byte[] buffer | |
* @return int indexToSkip | |
*/ | |
private int findIndexOfSequenceInByteArray(int[] sequence, byte[] buffer){ | |
int totalMatched = 0, indexToSkipHeader = 0; | |
// Search for first | |
for(byte value:buffer){ | |
indexToSkipHeader++; | |
// Convert byte to an integer | |
int signed = value & 0xFF; | |
// Increase total matches if signed integer matches integer sequence | |
if(signed == sequence[totalMatched]){ | |
totalMatched++; | |
}else{ | |
totalMatched = 0; | |
} | |
// If the total matched is equal to the sequence length, we have found the index | |
if(totalMatched == sequence.length){ | |
return indexToSkipHeader; | |
} | |
} | |
return FAILED_SEARCH_INDEX; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment