Adds basic support for native APIs for a local song player.
This commit is contained in:
1
WavReader/README.md
Normal file
1
WavReader/README.md
Normal file
@@ -0,0 +1 @@
|
||||
These files were originally posted by Andrii Tkachenko on GitHub in 2016. They have been refactored to function in a Gradle environment.
|
||||
11
WavReader/build.gradle
Normal file
11
WavReader/build.gradle
Normal file
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2021 William Hubbard. All Rights Reserved.
|
||||
*/
|
||||
|
||||
apply plugin: "java"
|
||||
apply plugin: "application"
|
||||
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
|
||||
mainClassName = "MetaReader"
|
||||
28
WavReader/src/main/java/MetaReader.java
Normal file
28
WavReader/src/main/java/MetaReader.java
Normal file
@@ -0,0 +1,28 @@
|
||||
import wave.WavHeader;
|
||||
import wave.WavHeaderReader;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Console utility for reading meta data of the wave files
|
||||
*/
|
||||
public class MetaReader {
|
||||
public static void main(String[] args) {
|
||||
if (args.length == 0) {
|
||||
System.out.println("Illegal command line arguments.\n" +
|
||||
"Usage MetaReader\n\t MetaReader <source file path>");
|
||||
return;
|
||||
}
|
||||
WavHeader wavHeader;
|
||||
try {
|
||||
WavHeaderReader wavHeaderReader = new WavHeaderReader(args[0]);
|
||||
wavHeader = wavHeaderReader.read();
|
||||
System.out.println(wavHeader.toString());
|
||||
} catch (FileNotFoundException e) {
|
||||
System.out.println("Error: File " + args[0] + " not found!");
|
||||
} catch (IOException e) {
|
||||
System.out.println("Error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
150
WavReader/src/main/java/wave/WavHeader.java
Normal file
150
WavReader/src/main/java/wave/WavHeader.java
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2016. Andrii Tkachenko. https://github.com/tkaczenko/WavReader
|
||||
*/
|
||||
|
||||
package wave;
|
||||
|
||||
/**
|
||||
* This class contains a structure of WAVE file.
|
||||
*
|
||||
* @see <a href =
|
||||
* "https://github.com/tkacz-/WavReader/blob/master/wav-sound-format.gif">
|
||||
* Structure of wave format
|
||||
* </a>
|
||||
*/
|
||||
public class WavHeader {
|
||||
private byte[] chunkID = new byte[4];
|
||||
private int chunkSize;
|
||||
private byte[] format = new byte[4];
|
||||
private byte[] subChunk1ID = new byte[4];
|
||||
private int subChunk1Size;
|
||||
private short audioFormat;
|
||||
private short numChannels;
|
||||
private int sampleRate;
|
||||
private int byteRate;
|
||||
private short blockAlign;
|
||||
private short bitsPerSample;
|
||||
private byte[] subChunk2ID = new byte[4];
|
||||
private int subChunk2Size;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "The RIFF chunk desriptor: " + new String(this.getChunkID()) + "\n" +
|
||||
"Size of this chunk: " + this.getChunkSize() + "\n" +
|
||||
"Format: " + new String(this.getFormat()) + "\n" + "\n" +
|
||||
"fmt subchunk: " + new String(this.getSubChunk1ID()) + "\n" +
|
||||
"Size of this chunk: " + this.getSubChunk1Size() + "\n" +
|
||||
"Audio format: " + this.getAudioFormat() + "\n" +
|
||||
"Number of channels: " + this.getNumChannels() + "\n" +
|
||||
"Sample rate: " + this.getSampleRate() + "\n" +
|
||||
"Byte rate: " + this.getByteRate() + "\n" +
|
||||
"Block align: " + this.getBlockAlign() + "\n" +
|
||||
"Bits per sample: " + this.getBitsPerSample() + "\n" + "\n" +
|
||||
"data subchunk: " + new String(this.getSubChunk2ID()) + "\n" +
|
||||
"Size of this chunk: " + this.getSubChunk2Size();
|
||||
}
|
||||
|
||||
public byte[] getChunkID() {
|
||||
return chunkID;
|
||||
}
|
||||
|
||||
public void setChunkID(byte[] chunkID) {
|
||||
this.chunkID = chunkID;
|
||||
}
|
||||
|
||||
public int getChunkSize() {
|
||||
return chunkSize;
|
||||
}
|
||||
|
||||
public void setChunkSize(int chunkSize) {
|
||||
this.chunkSize = chunkSize;
|
||||
}
|
||||
|
||||
public byte[] getFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
public void setFormat(byte[] format) {
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
public byte[] getSubChunk1ID() {
|
||||
return subChunk1ID;
|
||||
}
|
||||
|
||||
public void setSubChunk1ID(byte[] subChunk1ID) {
|
||||
this.subChunk1ID = subChunk1ID;
|
||||
}
|
||||
|
||||
public int getSubChunk1Size() {
|
||||
return subChunk1Size;
|
||||
}
|
||||
|
||||
public void setSubChunk1Size(int subChunk1Size) {
|
||||
this.subChunk1Size = subChunk1Size;
|
||||
}
|
||||
|
||||
public short getAudioFormat() {
|
||||
return audioFormat;
|
||||
}
|
||||
|
||||
public void setAudioFormat(short audioFormat) {
|
||||
this.audioFormat = audioFormat;
|
||||
}
|
||||
|
||||
public short getNumChannels() {
|
||||
return numChannels;
|
||||
}
|
||||
|
||||
public void setNumChannels(short numChannels) {
|
||||
this.numChannels = numChannels;
|
||||
}
|
||||
|
||||
public int getSampleRate() {
|
||||
return sampleRate;
|
||||
}
|
||||
|
||||
public void setSampleRate(int sampleRate) {
|
||||
this.sampleRate = sampleRate;
|
||||
}
|
||||
|
||||
public int getByteRate() {
|
||||
return byteRate;
|
||||
}
|
||||
|
||||
public void setByteRate(int byteRate) {
|
||||
this.byteRate = byteRate;
|
||||
}
|
||||
|
||||
public short getBlockAlign() {
|
||||
return blockAlign;
|
||||
}
|
||||
|
||||
public void setBlockAlign(short blockAlign) {
|
||||
this.blockAlign = blockAlign;
|
||||
}
|
||||
|
||||
public short getBitsPerSample() {
|
||||
return bitsPerSample;
|
||||
}
|
||||
|
||||
public void setBitsPerSample(short bitsPerSample) {
|
||||
this.bitsPerSample = bitsPerSample;
|
||||
}
|
||||
|
||||
public byte[] getSubChunk2ID() {
|
||||
return subChunk2ID;
|
||||
}
|
||||
|
||||
public void setSubChunk2ID(byte[] subChunk2ID) {
|
||||
this.subChunk2ID = subChunk2ID;
|
||||
}
|
||||
|
||||
public int getSubChunk2Size() {
|
||||
return subChunk2Size;
|
||||
}
|
||||
|
||||
public void setSubChunk2Size(int subChunk2Size) {
|
||||
this.subChunk2Size = subChunk2Size;
|
||||
}
|
||||
}
|
||||
159
WavReader/src/main/java/wave/WavHeaderReader.java
Normal file
159
WavReader/src/main/java/wave/WavHeaderReader.java
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (c) 2016. Andrii Tkachenko. https://github.com/tkaczenko/WavReader
|
||||
*/
|
||||
|
||||
package wave;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Custom wave header reader which use class
|
||||
*
|
||||
* @see WavHeader
|
||||
*/
|
||||
public class WavHeaderReader {
|
||||
/**
|
||||
* Size for the wave header
|
||||
*/
|
||||
private static final int HEADER_SIZE = 44;
|
||||
|
||||
/**
|
||||
* Buffer which contain bytes of the wave header
|
||||
*/
|
||||
private byte[] buf = new byte[HEADER_SIZE];
|
||||
|
||||
/**
|
||||
* Wave header
|
||||
*/
|
||||
private WavHeader header = new WavHeader();
|
||||
|
||||
/**
|
||||
* InputStream to the wave file
|
||||
*/
|
||||
private InputStream inputStream;
|
||||
|
||||
/**
|
||||
* Empty constructor
|
||||
*/
|
||||
public WavHeaderReader() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor which create own FileInputStream
|
||||
*
|
||||
* @param source absolute path to the file
|
||||
* @throws IOException
|
||||
*/
|
||||
public WavHeaderReader(String source) throws IOException {
|
||||
inputStream = new FileInputStream(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor which use created InputStream
|
||||
*
|
||||
* @param inputStream InputStream to the wave file
|
||||
*/
|
||||
public WavHeaderReader(InputStream inputStream) {
|
||||
this.inputStream = inputStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read wave header of the file
|
||||
*
|
||||
* @return wave.WavHeader object
|
||||
* @throws IOException
|
||||
* @see WavHeader
|
||||
*/
|
||||
public WavHeader read() throws IOException {
|
||||
int res = inputStream.read(buf);
|
||||
if (res != HEADER_SIZE) {
|
||||
throw new IOException("Could not read header.");
|
||||
}
|
||||
header.setChunkID(Arrays.copyOfRange(buf, 0, 4));
|
||||
if (new String(header.getChunkID()).compareTo("RIFF") != 0) {
|
||||
throw new IOException("Illegal format.");
|
||||
}
|
||||
header.setChunkSize(toInt(4, false));
|
||||
header.setFormat(Arrays.copyOfRange(buf, 8, 12));
|
||||
header.setSubChunk1ID(Arrays.copyOfRange(buf, 12, 16));
|
||||
header.setSubChunk1Size(toInt(16, false));
|
||||
header.setAudioFormat(toShort(20, false));
|
||||
header.setNumChannels(toShort(22, false));
|
||||
header.setSampleRate(toInt(24, false));
|
||||
header.setByteRate(toInt(28, false));
|
||||
header.setBlockAlign(toShort(32, false));
|
||||
header.setBitsPerSample(toShort(34, false));
|
||||
header.setSubChunk2ID(Arrays.copyOfRange(buf, 36, 40));
|
||||
header.setSubChunk2Size(toInt(40, false));
|
||||
return header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert byte[] array to int number
|
||||
*
|
||||
* @param start start position of the buffer
|
||||
* @param endian <code>true</code> for big-endian
|
||||
* <code>false</code> for little-endian
|
||||
* @return converted number
|
||||
*/
|
||||
private int toInt(int start, boolean endian) {
|
||||
int k = (endian) ? 1 : -1;
|
||||
if (!endian) {
|
||||
start += 3;
|
||||
}
|
||||
return (buf[start] << 24) + (buf[start + k * 1] << 16) +
|
||||
(buf[start + k * 2] << 8) + buf[start + k * 3];
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert byte[] array to short number
|
||||
*
|
||||
* @param start start position of the buffer
|
||||
* @param endian <code>true</code> for big-endian
|
||||
* <code>false</code> for little-endian
|
||||
* @return converted number
|
||||
*/
|
||||
private short toShort(int start, boolean endian) {
|
||||
short k = (endian) ? (short) 1 : -1;
|
||||
if (!endian) {
|
||||
start++;
|
||||
}
|
||||
return (short) ((buf[start] << 8) + (buf[start + k * 1]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the buffer which contain wave hader
|
||||
*
|
||||
* @return buffer
|
||||
*/
|
||||
public byte[] getBuf() {
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return wave.WavHeader object which contain wave header
|
||||
*
|
||||
* @return wave.WavHeader object
|
||||
*/
|
||||
public WavHeader getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return input stream to the wave file
|
||||
*
|
||||
* @return Input steam to the wave file
|
||||
*/
|
||||
public InputStream getInputStream() {
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
public void setInputStream(InputStream inputStream) {
|
||||
this.inputStream = inputStream;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user