Skip to content

Commit

Permalink
Uploading the wav analyzer
Browse files Browse the repository at this point in the history
  • Loading branch information
jukworks committed Nov 13, 2012
1 parent 509084e commit 44bfd73
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 0 deletions.
61 changes: 61 additions & 0 deletions WaveAnalyzer/src/commands/MusicAnalyzer.java
@@ -0,0 +1,61 @@
package commands;

import kr.ac.ajou.dv.musicfinder.analyzer.InvalidWaveFormatException;
import kr.ac.ajou.dv.musicfinder.analyzer.WaveHandler;
import kr.ac.ajou.dv.musicfinder.lib.DbSaveWorker;

import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.Properties;

public class MusicAnalyzer {
public static final String TEMPORARY_WAVE = "temp.wav";

public static void main(String[] args) {
Properties config = new Properties();
try {
config.load(new FileInputStream("analyzer.conf"));
} catch (IOException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
File mp3dir = new File(config.getProperty("mp3_directory"));
String soxParams = config.getProperty("sox_parameters");

WaveHandler wh = new WaveHandler();
DbSaveWorker dbSaveWorker = new DbSaveWorker();

for (File f : mp3dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return !dir.getName().endsWith(name);
}
})) {
if (!f.isDirectory() && f.getName().toLowerCase().endsWith(".mp3")) {
String songName = f.getName().substring(0, f.getName().length() - 4);
System.out.println(songName);
String command = "sox '" + f.getName() + "' " + soxParams + " '" + TEMPORARY_WAVE + "'";
ProcessBuilder pb = new ProcessBuilder("bash", "-c", command);
pb.directory(mp3dir);
try {
Process p = pb.start();
int exitValue = p.waitFor();
System.out.println("Converting to a Wave has been done (exit status: " + exitValue + ")");

File wav = new File(mp3dir + File.separator + TEMPORARY_WAVE);
if (wav.exists()) {
dbSaveWorker.addSong(songName);
wh.handle(wav, dbSaveWorker);
}
} catch (IOException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} catch (InvalidWaveFormatException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
}
}
}
36 changes: 36 additions & 0 deletions WaveAnalyzer/src/commands/MusicFinder.java
@@ -0,0 +1,36 @@
package commands;

import kr.ac.ajou.dv.musicfinder.analyzer.InvalidWaveFormatException;
import kr.ac.ajou.dv.musicfinder.analyzer.WaveHandler;
import kr.ac.ajou.dv.musicfinder.lib.DbQueryWorker;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.SortedMap;

public class MusicFinder {
public static void main(String[] args) {
File queryFile = new File("query/query-shining.wav");

WaveHandler wh = new WaveHandler();
DbQueryWorker dbQueryWorker = new DbQueryWorker();

try {
wh.handle(queryFile, dbQueryWorker);
SortedMap<Integer, List<Integer>> ranking = dbQueryWorker.getPoints();
for (int point : ranking.keySet()) {
System.out.print(point + " points: ");
for (int songId : ranking.get(point)) {
System.out.print(songId + " ");
}
System.out.println();
}
} catch (IOException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} catch (InvalidWaveFormatException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
}

@@ -0,0 +1,13 @@
package kr.ac.ajou.dv.musicfinder.analyzer;

/**
* Created with IntelliJ IDEA.
* User: dvlab
* Date: 11/7/12
* Time: 3:15 PM
* To change this template use File | Settings | File Templates.
*/
public class InvalidWaveFormatException extends Throwable {
public InvalidWaveFormatException(String s) {
}
}
@@ -0,0 +1,80 @@
package kr.ac.ajou.dv.musicfinder.analyzer;

import kr.ac.ajou.dv.musicfinder.lib.DbWorker;
import kr.ac.ajou.dv.musicfinder.lib.FftHelper;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.concurrent.ArrayBlockingQueue;

public class WaveHandler {
public static final int CHUNK_SIZE = 4096;
public static final int WINDOW_SIZE = 16;
public static final int SUB_CHUNK_SIZE = (CHUNK_SIZE / WINDOW_SIZE);
public static final int SHORT_BYTES = (Short.SIZE / Byte.SIZE);
public static final int NUMBER_OF_SAMPLES = (CHUNK_SIZE / SHORT_BYTES);

public void handle(File wav, DbWorker dbWorker) throws IOException, InvalidWaveFormatException {
FileInputStream fis = new FileInputStream(wav);
byte[] header = new byte[36];

fis.read(header);
if (!new String(header, 0, 4).equals("RIFF"))
throw new InvalidWaveFormatException("This file does not conform RIFF.");

if (!new String(header, 8, 4).equals("WAVE"))
throw new InvalidWaveFormatException("This is not a WAVE file.");

String subChunk1Id = new String(header, 12, 4);
int subChunk1Size = ByteBuffer.wrap(header, 16, 4).order(ByteOrder.LITTLE_ENDIAN).getInt();
short audioFormat = ByteBuffer.wrap(header, 20, 2).order(ByteOrder.LITTLE_ENDIAN).getShort();
short numChannels = ByteBuffer.wrap(header, 22, 2).order(ByteOrder.LITTLE_ENDIAN).getShort();
int sampleRate = ByteBuffer.wrap(header, 24, 4).order(ByteOrder.LITTLE_ENDIAN).getInt();
short bitsPerSample = ByteBuffer.wrap(header, 34, 2).order(ByteOrder.LITTLE_ENDIAN).getShort();

if (!subChunk1Id.equals("fmt ") ||
subChunk1Size != 16 ||
audioFormat != 1 ||
numChannels != 1 ||
sampleRate != 32000 ||
bitsPerSample != 16)
throw new InvalidWaveFormatException("Invalid 'fmt' sub-chunk.");

byte[] subChunk2Header = new byte[8];
fis.read(subChunk2Header);

String subChunk2Id = new String(subChunk2Header, 0, 4);
if (!subChunk2Id.equals("data"))
throw new InvalidWaveFormatException("Invalid 'data' sub-chunk.");

ArrayBlockingQueue<byte[]> queue = new ArrayBlockingQueue<byte[]>(WINDOW_SIZE);

int position = 0;
while (true) {
byte[] subChunk = new byte[SUB_CHUNK_SIZE];
if (fis.read(subChunk) < SUB_CHUNK_SIZE) break;
// In an initial state, the queue is not filled. We need the full 8 sub-chunks for the FFT transform.
if (queue.offer(subChunk)) continue;
queue.poll();
queue.offer(subChunk);

byte[] chunk = new byte[CHUNK_SIZE];
int offset = 0;
for (byte[] b : queue) {
System.arraycopy(b, 0, chunk, offset, SUB_CHUNK_SIZE);
offset += SUB_CHUNK_SIZE;
}
ByteBuffer sampleBuffer = ByteBuffer.wrap(chunk).order(ByteOrder.LITTLE_ENDIAN);

short[] pcm = new short[NUMBER_OF_SAMPLES];
for (int i = 0; i < NUMBER_OF_SAMPLES; i++)
pcm[i] = sampleBuffer.getShort();

int[] intensivePoints = FftHelper.getIntensivePointsAfterFft(pcm);
dbWorker.work(position++, DbWorker.fuzz(intensivePoints));
}
}
}

0 comments on commit 44bfd73

Please sign in to comment.