diff --git a/Fingerprinter/Audio/AudioDecoder.cs b/Fingerprinter/Audio/AudioDecoder.cs
index 7612b43..842e3fb 100644
--- a/Fingerprinter/Audio/AudioDecoder.cs
+++ b/Fingerprinter/Audio/AudioDecoder.cs
@@ -18,38 +18,6 @@ public abstract class AudioDecoder : IAudioDecoder
protected int sampleRate;
protected int channels;
- protected int sourceSampleRate;
- protected int sourceBitDepth;
- protected int sourceChannels;
- protected int duration;
-
- protected bool ready;
-
- public int SourceSampleRate
- {
- get { return sourceSampleRate; }
- }
-
- public int SourceBitDepth
- {
- get { return sourceBitDepth; }
- }
-
- public int SourceChannels
- {
- get { return sourceChannels; }
- }
-
- public int Duration
- {
- get { return duration; }
- }
-
- public bool Ready
- {
- get { return ready; }
- }
-
public int SampleRate
{
get { return sampleRate; }
@@ -60,7 +28,7 @@ public int Channels
get { return channels; }
}
- public abstract void Load(string file);
+ public AudioProperties Format { get; protected set; }
public abstract bool Decode(IAudioConsumer consumer, int maxLength);
diff --git a/Fingerprinter/Audio/AudioProperties.cs b/Fingerprinter/Audio/AudioProperties.cs
new file mode 100644
index 0000000..30b2c73
--- /dev/null
+++ b/Fingerprinter/Audio/AudioProperties.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Fingerprinter.Audio
+{
+ public class AudioProperties
+ {
+ ///
+ /// Gets the sample rate of the audio source.
+ ///
+ public int SampleRate { get; private set; }
+
+ ///
+ /// Gets the sample rate of the audio source (must be 16 bits per sample).
+ ///
+ public int BitDepth { get; private set; }
+
+ ///
+ /// Gets the number of channels.
+ ///
+ public int Channels { get; private set; }
+
+ ///
+ /// Gets the duration of the audio source (in seconds).
+ ///
+ public int Duration { get; private set; }
+
+ public AudioProperties()
+ : this(0, 0, 0, 0)
+ {
+ }
+
+ public AudioProperties(int sampleRate, int bitDepth, int channels, int duration)
+ {
+ this.SampleRate = sampleRate;
+ this.BitDepth = bitDepth;
+ this.Channels = channels;
+ this.Duration = duration;
+ }
+ }
+}
diff --git a/Fingerprinter/Audio/IAudioDecoder.cs b/Fingerprinter/Audio/IAudioDecoder.cs
index 8c023a9..f19e1eb 100644
--- a/Fingerprinter/Audio/IAudioDecoder.cs
+++ b/Fingerprinter/Audio/IAudioDecoder.cs
@@ -14,16 +14,6 @@ namespace Fingerprinter.Audio
///
public interface IAudioDecoder : IDecoder, IDisposable
{
- int SourceSampleRate { get; }
- int SourceBitDepth { get; }
- int SourceChannels { get; }
-
- int Duration { get; }
- bool Ready { get; }
-
- ///
- /// Load an audio file.
- ///
- void Load(string file);
+ AudioProperties Format { get; }
}
}
diff --git a/Fingerprinter/Audio/NAudioDecoder.cs b/Fingerprinter/Audio/NAudioDecoder.cs
index 6b8582f..6fe0c87 100644
--- a/Fingerprinter/Audio/NAudioDecoder.cs
+++ b/Fingerprinter/Audio/NAudioDecoder.cs
@@ -12,53 +12,32 @@ namespace Fingerprinter.Audio
using NAudio.Wave;
///
- /// Decode using the NAudio library. Great audio library, but the MP3 decoder is kinda slow.
+ /// Decode using the NAudio library..
///
public class NAudioDecoder : AudioDecoder
{
WaveStream reader;
- string extension;
-
- public override void Load(string file)
- {
- // Dispose on every new load
- Dispose(false);
-
- ready = false;
-
- extension = Path.GetExtension(file).ToLowerInvariant();
+ string file;
- if (extension.Equals(".wav"))
- {
- reader = new WaveFileReader(file);
- }
- else
- {
- reader = new Mp3FileReader(file);
- }
-
- var format = reader.WaveFormat;
-
- this.sampleRate = format.SampleRate;
- this.channels = format.Channels;
+ public NAudioDecoder(string file)
+ {
+ this.file = file;
- this.sourceSampleRate = format.SampleRate;
- this.sourceBitDepth = format.BitsPerSample;
- this.sourceChannels = format.Channels;
- this.duration = (int)reader.TotalTime.TotalSeconds;
- this.ready = (format.BitsPerSample == 16);
+ // Open the WaveStream and keep it open until Dispose() is called. This might lock
+ // the file. A better approach would be to open the stream only when needed.
+ Initialize();
}
public override bool Decode(IAudioConsumer consumer, int maxLength)
{
- if (!ready) return false;
+ if (reader == null) return false;
int remaining, length, size;
byte[] buffer = new byte[2 * BUFFER_SIZE];
short[] data = new short[BUFFER_SIZE];
// Samples to read to get maxLength seconds of audio
- remaining = maxLength * this.sourceChannels * this.sampleRate;
+ remaining = maxLength * this.Format.Channels * this.sampleRate;
// Bytes to read
length = 2 * Math.Min(remaining, BUFFER_SIZE);
@@ -81,6 +60,33 @@ public override bool Decode(IAudioConsumer consumer, int maxLength)
return true;
}
+ private void Initialize()
+ {
+ var extension = Path.GetExtension(file).ToLowerInvariant();
+
+ if (extension.Equals(".wav"))
+ {
+ reader = new WaveFileReader(file);
+ }
+ else
+ {
+ reader = new Mp3FileReader(file);
+ }
+
+ var format = reader.WaveFormat;
+
+ this.sampleRate = format.SampleRate;
+ this.channels = format.Channels;
+
+ this.Format = new AudioProperties(format.SampleRate, format.BitsPerSample,
+ format.Channels, (int)reader.TotalTime.TotalSeconds);
+
+ if (format.BitsPerSample != 16)
+ {
+ Dispose(true);
+ }
+ }
+
#region IDisposable implementation
private bool hasDisposed = false;
@@ -99,6 +105,7 @@ public void Dispose(bool disposing)
{
reader.Close();
reader.Dispose();
+ reader = null;
}
}
diff --git a/Fingerprinter/Fingerprinter.csproj b/Fingerprinter/Fingerprinter.csproj
index a5eac2f..8a0f0e2 100644
--- a/Fingerprinter/Fingerprinter.csproj
+++ b/Fingerprinter/Fingerprinter.csproj
@@ -36,9 +36,9 @@
4
-
- False
- ..\packages\NAudio.1.7.2\lib\net35\NAudio.dll
+
+ ..\packages\NAudio.1.7.3\lib\net35\NAudio.dll
+ True
@@ -46,6 +46,7 @@
+
diff --git a/Fingerprinter/MainForm.cs b/Fingerprinter/MainForm.cs
index cf53ac7..aa778aa 100644
--- a/Fingerprinter/MainForm.cs
+++ b/Fingerprinter/MainForm.cs
@@ -1,14 +1,14 @@
-using System;
+using AcoustID;
+using AcoustID.Web;
+using Fingerprinter.Audio;
+using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
+using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
-using AcoustID;
-using AcoustID.Web;
-using Fingerprinter.Audio;
-using System.Threading;
namespace Fingerprinter
{
@@ -24,9 +24,6 @@ public MainForm()
private void MainForm_Load(object sender, EventArgs e)
{
Fpcalc.Path = @"D:\Projects\AcoustId\extern\fpcalc.exe";
-
- decoder = new NAudioDecoder();
- //decoder = new BassDecoder();
}
private void btnOpen_Click(object sender, EventArgs e)
@@ -36,26 +33,32 @@ private void btnOpen_Click(object sender, EventArgs e)
if (dlg.ShowDialog() == DialogResult.OK)
{
- lbFile.Text = dlg.FileName;
+ if (decoder != null)
+ {
+ decoder.Dispose();
+ }
- ResetAll();
+ try
+ {
+ decoder = new NAudioDecoder(dlg.FileName);
+ //decoder = new BassDecoder();
- decoder.Load(dlg.FileName);
+ lbFile.Text = dlg.FileName;
- int bits = decoder.SourceBitDepth;
- int channels = decoder.SourceChannels;
+ ResetAll();
+
+ int bits = decoder.Format.BitDepth;
+ int channels = decoder.Format.Channels;
- if (decoder.Ready)
- {
lbAudio.Text = String.Format("{0}Hz, {1}bit{2}, {3}",
- decoder.SourceSampleRate, bits, bits != 16 ? " (not supported)" : "",
+ decoder.Format.SampleRate, bits, bits != 16 ? " (not supported)" : "",
channels == 2 ? "stereo" : (channels == 1 ? "mono" : "multi-channel"));
- lbDuration.Text = decoder.Duration.ToString();
+ lbDuration.Text = decoder.Format.Duration.ToString();
btnFingerPrint.Enabled = true;
}
- else
+ catch
{
lbAudio.Text = "Failed to load audio";
lbDuration.Text = String.Empty;
@@ -244,7 +247,7 @@ private void ProcessFile(string file)
{
if (File.Exists(file))
{
- if (decoder.Ready)
+ if (decoder != null)
{
//btnOpen.Enabled = false;
btnFingerPrint.Enabled = false;
diff --git a/Fingerprinter/packages.config b/Fingerprinter/packages.config
index 1e2c8b7..b19b834 100644
--- a/Fingerprinter/packages.config
+++ b/Fingerprinter/packages.config
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file