summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/simpl/peak_detection.cpp120
-rw-r--r--src/simpl/peak_detection.h50
-rw-r--r--src/sms/sms.h4
3 files changed, 155 insertions, 19 deletions
diff --git a/src/simpl/peak_detection.cpp b/src/simpl/peak_detection.cpp
index 1d44b6f..7a31846 100644
--- a/src/simpl/peak_detection.cpp
+++ b/src/simpl/peak_detection.cpp
@@ -113,6 +113,10 @@ Frames PeakDetection::frames() {
return _frames;
}
+void PeakDetection::frames(Frames new_frames) {
+ _frames = new_frames;
+}
+
// Find and return all spectral peaks in a given frame of audio
Peaks PeakDetection::find_peaks_in_frame(Frame* frame) {
Peaks peaks;
@@ -153,4 +157,120 @@ Frames PeakDetection::find_peaks(int audio_size, sample* audio) {
// SMSPeakDetection
// ---------------------------------------------------------------------------
SMSPeakDetection::SMSPeakDetection() {
+ sms_init();
+
+ sms_initAnalParams(&_analysis_params);
+ _analysis_params.iSamplingRate = _sampling_rate;
+ _analysis_params.iFrameRate = _sampling_rate / _hop_size;
+ _analysis_params.iWindowType = SMS_WIN_HAMMING;
+ _analysis_params.fHighestFreq = 20000;
+ _analysis_params.iMaxDelayFrames = 4;
+ _analysis_params.analDelay = 0;
+ _analysis_params.minGoodFrames = 1;
+ _analysis_params.iCleanTracks = 0;
+ _analysis_params.iFormat = SMS_FORMAT_HP;
+ _analysis_params.nTracks = _max_peaks;
+ _analysis_params.maxPeaks = _max_peaks;
+ _analysis_params.nGuides = _max_peaks;
+ _analysis_params.preEmphasis = 0;
+ sms_initAnalysis(&_analysis_params);
+
+ sms_initSpectralPeaks(&_peaks, _max_peaks);
+
+ // By default, SMS will change the size of the frames being read
+ // depending on the detected fundamental frequency (if any) of the
+ // input sound. To prevent this behaviour (useful when comparing
+ // different analysis algorithms), set the
+ // _static_frame_size variable to True
+ _static_frame_size = false;
+}
+
+SMSPeakDetection::~SMSPeakDetection() {
+ sms_freeAnalysis(&_analysis_params);
+ sms_freeSpectralPeaks(&_peaks);
+ sms_free();
+}
+
+int SMSPeakDetection::next_frame_size() {
+ return _analysis_params.sizeNextRead;
+}
+
+void SMSPeakDetection::hop_size(int new_hop_size) {
+ _hop_size = new_hop_size;
+ sms_freeAnalysis(&_analysis_params);
+ _analysis_params.iFrameRate = _sampling_rate / _hop_size;
+ sms_initAnalysis(&_analysis_params);
+}
+
+void SMSPeakDetection::max_peaks(int new_max_peaks) {
+ _max_peaks = new_max_peaks;
+ if(_max_peaks > SMS_MAX_NPEAKS) {
+ _max_peaks = SMS_MAX_NPEAKS;
+ }
+
+ sms_freeAnalysis(&_analysis_params);
+ sms_freeSpectralPeaks(&_peaks);
+
+ _analysis_params.nTracks = _max_peaks;
+ _analysis_params.maxPeaks = _max_peaks;
+ _analysis_params.nGuides = _max_peaks;
+
+ sms_initAnalysis(&_analysis_params);
+ sms_initSpectralPeaks(&_peaks, _max_peaks);
+}
+
+// Find and return all spectral peaks in a given frame of audio
+Peaks SMSPeakDetection::find_peaks_in_frame(Frame* frame) {
+ Peaks peaks;
+
+ int num_peaks = sms_findPeaks(frame->size(), frame->audio(),
+ &_analysis_params, &_peaks);
+
+ for(int i = 0; i < num_peaks; i++) {
+ Peak* p = new Peak();
+ p->amplitude = _peaks.pSpectralPeaks[i].fMag;
+ p->frequency = _peaks.pSpectralPeaks[i].fFreq;
+ p->phase = _peaks.pSpectralPeaks[i].fPhase;
+ peaks.push_back(p);
+ }
+ return peaks;
+}
+
+// Find and return all spectral peaks in a given audio signal.
+// If the signal contains more than 1 frame worth of audio,
+// it will be broken up into separate frames, with a list of
+// peaks returned for each frame.
+//
+// TODO: This hops by frame size rather than hop size in order to
+// make sure the results are the same as with libsms. Make sure
+// we have the same number of frames as the other algorithms.
+Frames SMSPeakDetection::find_peaks(int audio_size, sample* audio) {
+ clear();
+
+ _analysis_params.iSizeSound = audio_size;
+ unsigned int pos = 0;
+
+ // account for SMS analysis delay
+ // need an extra (max_frame_delay - 1) frames
+ int delay = (_analysis_params.iMaxDelayFrames - 1) & _hop_size;
+
+ while(pos < ((audio_size - _hop_size) + delay)) {
+ // get the next frame size
+ if(!_static_frame_size) {
+ _frame_size = next_frame_size();
+ }
+
+ // get the next frame
+ Frame* f = new Frame(_frame_size);
+ f->audio(&audio[pos]);
+
+ // find peaks
+ Peaks peaks = find_peaks_in_frame(f);
+ f->add_peaks(&peaks);
+
+ _frames.push_back(f);
+ pos += _frame_size;
+ }
+
+ return _frames;
}
diff --git a/src/simpl/peak_detection.h b/src/simpl/peak_detection.h
index 0045762..577e0b5 100644
--- a/src/simpl/peak_detection.h
+++ b/src/simpl/peak_detection.h
@@ -3,8 +3,13 @@
#include "base.h"
+extern "C" {
+ #include "sms.h"
+}
+
using namespace std;
+
namespace simpl
{
@@ -16,7 +21,7 @@ namespace simpl
// ---------------------------------------------------------------------------
class PeakDetection {
- private:
+ protected:
int _sampling_rate;
int _frame_size;
bool _static_frame_size;
@@ -32,26 +37,27 @@ class PeakDetection {
virtual ~PeakDetection();
void clear();
- int sampling_rate();
- void sampling_rate(int new_sampling_rate);
- int frame_size();
- void frame_size(int new_frame_size);
- bool static_frame_size();
- void static_frame_size(bool new_static_frame_size);
+ virtual int sampling_rate();
+ virtual void sampling_rate(int new_sampling_rate);
+ virtual int frame_size();
+ virtual void frame_size(int new_frame_size);
+ virtual bool static_frame_size();
+ virtual void static_frame_size(bool new_static_frame_size);
virtual int next_frame_size();
- int hop_size();
- void hop_size(int new_hop_size);
- int max_peaks();
- void max_peaks(int new_max_peaks);
- std::string window_type();
- void window_type(std::string new_window_type);
- int window_size();
- void window_size(int new_window_size);
- sample min_peak_separation();
- void min_peak_separation(sample new_min_peak_separation);
+ virtual int hop_size();
+ virtual void hop_size(int new_hop_size);
+ virtual int max_peaks();
+ virtual void max_peaks(int new_max_peaks);
+ virtual std::string window_type();
+ virtual void window_type(std::string new_window_type);
+ virtual int window_size();
+ virtual void window_size(int new_window_size);
+ virtual sample min_peak_separation();
+ virtual void min_peak_separation(sample new_min_peak_separation);
int num_frames();
Frame* frame(int frame_number);
Frames frames();
+ void frames(Frames new_frames);
// Find and return all spectral peaks in a given frame of audio
virtual Peaks find_peaks_in_frame(Frame* frame);
@@ -67,8 +73,18 @@ class PeakDetection {
// SMSPeakDetection
// ---------------------------------------------------------------------------
class SMSPeakDetection : public PeakDetection {
+ private:
+ SMSAnalysisParams _analysis_params;
+ SMSSpectralPeaks _peaks;
+
public:
SMSPeakDetection();
+ ~SMSPeakDetection();
+ int next_frame_size();
+ void hop_size(int new_hop_size);
+ void max_peaks(int new_max_peaks);
+ Peaks find_peaks_in_frame(Frame* frame);
+ Frames find_peaks(int audio_size, sample* audio);
};
diff --git a/src/sms/sms.h b/src/sms/sms.h
index 0613ab3..4e6e5c1 100644
--- a/src/sms/sms.h
+++ b/src/sms/sms.h
@@ -132,7 +132,7 @@ typedef struct
} SMS_Peak;
/* a collection of spectral peaks */
-typedef struct
+typedef struct SMSSpectralPeaks
{
SMS_Peak *pSpectralPeaks;
int nPeaks;
@@ -228,7 +228,7 @@ typedef struct
* and peak detection/continuation process can be re-computed with more accuracy.
*
*/
-typedef struct
+typedef struct SMSAnalysisParams
{
int iDebugMode; /*!< debug codes enumerated by SMS_DBG \see SMS_DBG */
int iFormat; /*!< analysis format code defined by SMS_Format \see SMS_Format */