Skip to content
Permalink
Browse files

eml_audio: More tests for melspec

  • Loading branch information...
jonnor committed Dec 29, 2018
1 parent 147160a commit dfb070fc598ecaccdab98eccc2f9d67d48d7c9bf
Showing with 99 additions and 10 deletions.
  1. +33 −0 bindings/eml_audio.cpp
  2. +66 −10 test/test_audio.py
@@ -54,6 +54,34 @@ rfft_py(py::array_t<float, py::array::c_style | py::array::forcecast> in) {
return ret;
}

py::array_t<float>
melfilter_py(py::array_t<float, py::array::c_style | py::array::forcecast> in,
int samplerate, int n_fft, int n_mels, float fmin, float fmax
)
{
if (in.ndim() != 1) {
throw std::runtime_error("melfilter() input must have dimensions 1");
}
if (in.shape(0) != 1+(n_fft/2)) {
throw std::runtime_error("framing not implented");
}

const EmlAudioMel params = { n_mels, fmin, fmax, n_fft, samplerate };

// Copy input to avoid modifying
const int length = in.shape(0);
EmlVector inv = {(float *)in.data(), length};
// Prepare output
auto ret = py::array_t<float>(params.n_mels);
EmlVector outv = { (float *)ret.data(), params.n_mels };
// Run
const EmlError error = eml_audio_melspec(params, inv, outv);
if (error != EmlOk) {
throw std::runtime_error("melspec() returned error: " + std::string(eml_error_str(error)));
}
return ret;
}


py::array_t<float>
melspectrogram_py(py::array_t<float, py::array::c_style | py::array::forcecast> in,
@@ -101,10 +129,15 @@ melspectrogram_py(py::array_t<float, py::array::c_style | py::array::forcecast>
return ret;
}



PYBIND11_MODULE(eml_audio, m) {
m.doc() = "Audio machine learning for microcontrollers and embedded devices";

m.def("rfft", rfft_py);
m.def("melfilter", melfilter_py);

m.def("melspectrogram", melspectrogram_py);

}

@@ -5,6 +5,11 @@
import pytest
import numpy.testing

import matplotlib
matplotlib.use('Agg')
import librosa
import librosa.display

import emlearn
import eml_audio

@@ -23,27 +28,78 @@ def test_rfft_simple(n_fft):
out = eml_audio.rfft(signal)
diff = (out - ref)

numpy.testing.assert_allclose(out, ref, rtol=1e-5)
numpy.testing.assert_allclose(out, ref, rtol=1e-4)

def test_rfft_not_power2_length():
with pytest.raises(Exception) as e:
eml_audio.rfft(numpy.array([0,1,3,4,5]))

@pytest.mark.skip('wrong scaling?')

@pytest.mark.skip('broken')
def test_melfilter():
filename = librosa.util.example_audio_file()
y, sr = librosa.load(filename, offset=1.0, duration=0.3)
n_fft = 1024
hop_length = 256
fmin = 500
fmax = 5000
n_mels = 32

spec = numpy.abs(librosa.core.stft(y, n_fft=n_fft, hop_length=hop_length))**2
spec1 = spec[:,0]

ref = librosa.feature.melspectrogram(S=spec1, sr=sr, htk=True, n_fft=n_fft, n_mels=n_mels, fmin=fmin, fmax=fmax)
out = eml_audio.melfilter(spec1, sr, n_fft, n_mels, fmin, fmax)

assert ref.shape == out.shape
numpy.testing.assert_array_almost_equal(ref, out)


@pytest.mark.skip('broken')
def test_melspectrogram():

import librosa
filename = librosa.util.example_audio_file()

y, sr = librosa.load(filename, offset=1.0, duration=0.3)

n_mels = 64
n_fft = 1024
fmin = 500
fmax = 5000
hop_size = n_fft

# Only do one frame
y = y[0:n_fft]
ref = librosa.feature.melspectrogram(y, sr, norm=None, htk=True,
fmin=fmin, fmax=fmax, n_fft=n_fft, n_mels=n_mels, hop_length=hop_size)
out = eml_audio.melspectrogram(y, sr, n_fft, n_mels, fmin, fmax)
ref = ref[:,0:1]
out = out.reshape(-1,1)

#out = melspec(y, sr, n_fft, n_mels, fmin, fmax, hop_length=hop_size)[:,:10]

print('r', ref.shape)

assert out.shape == ref.shape

y, sr = librosa.load('data/ff1010bird/{}.wav'.format(19037), offset=0)
from matplotlib import pyplot as plt
fig, (ref_ax, out_ax) = plt.subplots(2)
def specshow(d, ax):
s = librosa.amplitude_to_db(d, ref=numpy.max)
librosa.display.specshow(s, ax=ax, x_axis='time')
#librosa.display.specshow(s, ax=ax, x_axis='time', y_axis='mel', fmin=fmin, fmax=fmax)
specshow(ref, ax=ref_ax)
specshow(out, ax=out_ax)

ref = librosa.feature.melspectrogram(y, sr, fmin=0, fmax=None, n_fft=1024, n_mels=64, norm=None, htk=True)
out = eml_audio.melspectrogram(y, sr, n_fft=1024, fmin=0, fmax=None, n_mels=64)
ref = ref[:,1:-1]
fig.savefig('melspec.png')

print(numpy.mean(ref))
print(numpy.mean(out))
print('mean', numpy.mean(ref), numpy.mean(out))
print('std', numpy.std(ref), numpy.std(out))
s = numpy.mean(ref) / numpy.mean(out)
print('scale', s)
out = out * s

print(out-ref)
#print(out-ref)
numpy.testing.assert_allclose(out, ref, rtol=1e-6);


0 comments on commit dfb070f

Please sign in to comment.
You can’t perform that action at this time.