Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for sound file input and enhanced audio processing #241

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/main/java/io/WAVFile.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io;

import java.util.List;

public class WAVFile {
WAVHeader header;
private final List<Short> data;

public WAVFile(WAVHeader header, List<Short> data) {
this.header = header;
this.data = data;
}


public List<Short> getData() {
return data;
}
}


17 changes: 17 additions & 0 deletions src/main/java/io/WAVHeader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io;

public class WAVHeader {
byte[] riff = new byte[4]; // "RIFF"
int chunkSize; // File size - 8 bytes
byte[] wave = new byte[4]; // "WAVE"
byte[] fmt = new byte[4]; // "fmt "
int subchunk1Size; // PCM: 16
short audioFormat; // PCM = 1
short numChannels; // Mono = 1, Stereo = 2
int sampleRate; // Samples per second
int byteRate; // sampleRate * numChannels * bitsPerSample / 8
short blockAlign; // numChannels * bitsPerSample / 8
short bitsPerSample; // 8 bits = 8, 16 bits = 16
byte[] data = new byte[4]; // "data"
int dataSize; // Number of bytes in data section
}
103 changes: 103 additions & 0 deletions src/main/java/io/WAVProcessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package io;

import java.io.*;
import java.util.ArrayList;
import java.util.List;


public class WAVProcessor {

public static WAVFile readWAV(String filename) throws IOException {
try (DataInputStream dis = new DataInputStream(new FileInputStream(filename))) {
WAVHeader header = new WAVHeader();

dis.readFully(header.riff);
header.chunkSize = Integer.reverseBytes(dis.readInt());
dis.readFully(header.wave);
dis.readFully(header.fmt);
header.subchunk1Size = Integer.reverseBytes(dis.readInt());
header.audioFormat = Short.reverseBytes(dis.readShort());
header.numChannels = Short.reverseBytes(dis.readShort());
header.sampleRate = Integer.reverseBytes(dis.readInt());
header.byteRate = Integer.reverseBytes(dis.readInt());
header.blockAlign = Short.reverseBytes(dis.readShort());
header.bitsPerSample = Short.reverseBytes(dis.readShort());
dis.readFully(header.data);
header.dataSize = Integer.reverseBytes(dis.readInt());

// Read audio data
List<Short> audioData = new ArrayList<>();
for (int i = 0; i < header.dataSize / 2; i++) {
audioData.add(Short.reverseBytes(dis.readShort()));
}
return new WAVFile(header, audioData);
}
}

public static void writeWAV(String filename, WAVHeader header, List<Short> audioData) throws IOException {
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(filename))) {
dos.write(header.riff);
dos.writeInt(Integer.reverseBytes(header.chunkSize));
dos.write(header.wave);
dos.write(header.fmt);
dos.writeInt(Integer.reverseBytes(header.subchunk1Size));
dos.writeShort(Short.reverseBytes(header.audioFormat));
dos.writeShort(Short.reverseBytes(header.numChannels));
dos.writeInt(Integer.reverseBytes(header.sampleRate));
dos.writeInt(Integer.reverseBytes(header.byteRate));
dos.writeShort(Short.reverseBytes(header.blockAlign));
dos.writeShort(Short.reverseBytes(header.bitsPerSample));
dos.write(header.data);
dos.writeInt(Integer.reverseBytes(header.dataSize));

for (short sample : audioData) {
dos.writeShort(Short.reverseBytes(sample));
}
}
}

public static List<Short> addEcho(List<Short> audioData, int sampleRate, float delaySeconds, float decayFactor) {
List<Short> echoedData = new ArrayList<>(audioData);
int delaySamples = (int) (sampleRate * delaySeconds);

for (int i = delaySamples; i < audioData.size(); i++) {
short echo = (short) (audioData.get(i - delaySamples) * decayFactor);
echoedData.set(i, (short) (audioData.get(i) + echo));
}
return echoedData;
}

public static WAVHeader changeSpeedHeader(WAVHeader header, float speedFactor) {
header.sampleRate = (int) (header.sampleRate * speedFactor);
header.byteRate = header.sampleRate * header.numChannels * header.bitsPerSample / 8;
return header;
}

public static List<Short> reverseAudio(List<Short> audioData) {
List<Short> reversedData = new ArrayList<>(audioData);
for (int i = 0, j = reversedData.size() - 1; i < j; i++, j--) {
short temp = reversedData.get(i);
reversedData.set(i, reversedData.get(j));
reversedData.set(j, temp);
}
return reversedData;
}

public static void main(String[] args) {
try {
// Read WAV file
WAVFile wavFile = readWAV("C:/Users/CRIZMA MEGA STORE/Desktop/OpenGL-Lab-New/vendor\\SDL2\\test");

// Process WAV
List<Short> echoedData = addEcho(wavFile.getData(), wavFile.header.sampleRate, 0.5f, 0.6f);
WAVHeader newHeader = changeSpeedHeader(wavFile.header, 1.5f);
List<Short> reversedData = reverseAudio(echoedData);

// Write output
writeWAV("output.wav", newHeader, reversedData);
} catch (IOException e) {
e.printStackTrace();
}
}
}

66 changes: 66 additions & 0 deletions src/test/java/WAVProcessorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import io.WAVProcessor;

import java.util.Arrays;
import java.util.List;

public class WAVProcessorTest {

public static void testAddEcho() {
List<Short> input = Arrays.asList((short) 1000, (short) 2000, (short) 3000, (short) 4000, (short) 5000);
int sampleRate = 5; // Sample rate in samples per second
float delaySeconds = 0.2f; // 200ms delay
float decayFactor = 0.5f; // 50% decay for echo

List<Short> expectedOutput = Arrays.asList((short) 1000, (short) 2000, (short) 3500, (short) 5000, (short) 6500);

List<Short> actualOutput = WAVProcessor.addEcho(input, sampleRate, delaySeconds, decayFactor);

if (expectedOutput.equals(actualOutput)) {
System.out.println("testAddEcho PASSED");
} else {
System.out.println("testAddEcho FAILED");
}
}

public static void testReverseAudio() {
List<Short> input = Arrays.asList((short) 1, (short) 2, (short) 3, (short) 4, (short) 5);
List<Short> expectedOutput = Arrays.asList((short) 5, (short) 4, (short) 3, (short) 2, (short) 1);

List<Short> actualOutput = WAVProcessor.reverseAudio(input);

if (expectedOutput.equals(actualOutput)) {
System.out.println("testReverseAudio PASSED");
} else {
System.out.println("testReverseAudio FAILED");
}
}

public static void testWriteAndReadWAV() {
try {
// Input test data
List<Short> audioData = Arrays.asList((short) 1000, (short) 2000, (short) 3000, (short) 4000, (short) 5000);
String testFile = "test.wav";

// Write the test data
WAVProcessor.writeWAV(testFile, null, audioData);

// Read back the written data
List<Short> readData = WAVProcessor.readWAV(testFile).getData();

if (readData.equals(audioData)) {
System.out.println("testWriteAndReadWAV PASSED");
} else {
System.out.println("testWriteAndReadWAV FAILED");
}
} catch (Exception e) {
System.out.println("testWriteAndReadWAV FAILED with exception: " + e.getMessage());
}
}

public static void main(String[] args) {
testAddEcho();
testReverseAudio();
testWriteAndReadWAV();
}
}

Loading