-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
343 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
#pragma once | ||
|
||
/**------------------------------------------------------------------------- | ||
* @file fftbuffer.h | ||
* @brief Stores one or more spectra of FFT mag/phase pairs. | ||
* | ||
*-----------------------------------------------------------------------*/ | ||
|
||
#include "signalflow/core/constants.h" | ||
#include "signalflow/core/util.h" | ||
|
||
#include <functional> | ||
#include <iostream> | ||
#include <memory> | ||
#include <string> | ||
#include <vector> | ||
|
||
namespace signalflow | ||
{ | ||
|
||
template <class T> | ||
class FFTBufferRefTemplate; | ||
class FFTBuffer; | ||
typedef FFTBufferRefTemplate<FFTBuffer> FFTBufferRef; | ||
|
||
class FFTBuffer | ||
{ | ||
public: | ||
/**------------------------------------------------------------------------ | ||
* Construct an FFT buffer of specified dimensions. | ||
* The contents are initialised to zero. | ||
* | ||
*------------------------------------------------------------------------*/ | ||
FFTBuffer(int num_frames, int fft_size, int hop_size); | ||
|
||
/**------------------------------------------------------------------------ | ||
* Load the contents of the spectra file `filename` into a new buffer. | ||
* | ||
*------------------------------------------------------------------------*/ | ||
FFTBuffer(std::string filename, int fft_size, int hop_size); | ||
|
||
/**------------------------------------------------------------------------ | ||
* Destroy the buffer. | ||
* | ||
*------------------------------------------------------------------------*/ | ||
virtual ~FFTBuffer(); | ||
|
||
/**------------------------------------------------------------------------ | ||
* Resize the FFT buffer. | ||
* | ||
* @param num_frames The number of FFT frames to allocate. | ||
* | ||
*------------------------------------------------------------------------*/ | ||
void resize(int num_frames); | ||
|
||
/**------------------------------------------------------------------------ | ||
* Get the magnitude array corresponding to the given frame. | ||
* | ||
* @param frame The frame index, between [0, num_frames]. | ||
* @returns A sample value, between [-1, 1]. | ||
* | ||
*------------------------------------------------------------------------*/ | ||
sample *get_magnitudes(int frame); | ||
sample *get_phases(int frame); | ||
|
||
/**------------------------------------------------------------------------ | ||
* Get the buffer's audio sample rate. | ||
* | ||
* @returns The sample rate, in Hz. | ||
* | ||
*------------------------------------------------------------------------*/ | ||
float get_sample_rate(); | ||
|
||
/**------------------------------------------------------------------------ | ||
* Set the buffer's audio sample rate. | ||
* | ||
* @param sample_rate The sample rate | ||
* | ||
*------------------------------------------------------------------------*/ | ||
void set_sample_rate(float sample_rate); | ||
|
||
/**------------------------------------------------------------------------ | ||
* Get the number of spectrum frames in the buffer. | ||
* | ||
* @returns The number of frames. | ||
* | ||
*------------------------------------------------------------------------*/ | ||
unsigned long get_num_frames(); | ||
|
||
/**------------------------------------------------------------------------ | ||
* Get the duration of the buffer, based on the hop_size. | ||
* | ||
* @returns The duration, in seconds. | ||
* | ||
*------------------------------------------------------------------------*/ | ||
float get_duration(); | ||
|
||
/**------------------------------------------------------------------------ | ||
* Get the buffer's FFT size. | ||
* | ||
* @returns The FFT size. | ||
* | ||
*------------------------------------------------------------------------*/ | ||
unsigned int get_fft_size(); | ||
|
||
/**------------------------------------------------------------------------ | ||
* Get the buffer's hop size. | ||
* | ||
* @returns The hop size. | ||
* | ||
*------------------------------------------------------------------------*/ | ||
unsigned int get_hop_size(); | ||
|
||
/**------------------------------------------------------------------------ | ||
* Get the filename that the buffer was loaded from / saved to, if set. | ||
* | ||
* @returns The filename, or an empty string. | ||
* | ||
*------------------------------------------------------------------------*/ | ||
std::string get_filename(); | ||
|
||
sample **data = nullptr; | ||
|
||
protected: | ||
unsigned long get_total_num_values(); | ||
|
||
std::string filename; | ||
float sample_rate; | ||
unsigned int num_frames; | ||
unsigned int fft_size; | ||
unsigned int num_bins; | ||
unsigned int hop_size; | ||
float duration; | ||
}; | ||
|
||
template <class T> | ||
class FFTBufferRefTemplate : public std::shared_ptr<T> | ||
{ | ||
public: | ||
using std::shared_ptr<T>::shared_ptr; | ||
|
||
FFTBufferRefTemplate() | ||
: std::shared_ptr<T>(nullptr) {} | ||
FFTBufferRefTemplate(T *ptr) | ||
: std::shared_ptr<T>(ptr) {} | ||
}; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
#include "signalflow/buffer/fftbuffer.h" | ||
#include "signalflow/core/constants.h" | ||
#include "signalflow/core/exceptions.h" | ||
#include "signalflow/core/graph.h" | ||
|
||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
|
||
#ifdef WIN32 | ||
#include <io.h> | ||
#else | ||
#include <unistd.h> | ||
#endif | ||
|
||
#include <vector> | ||
|
||
namespace signalflow | ||
{ | ||
|
||
extern AudioGraph *shared_graph; | ||
|
||
FFTBuffer::FFTBuffer(std::string filename, int fft_size, int hop_size) | ||
: fft_size(fft_size), hop_size(hop_size) | ||
{ | ||
this->num_bins = (fft_size / 2) + 1; | ||
|
||
FILE *fd = fopen(filename.c_str(), "r"); | ||
if (fd == NULL) | ||
{ | ||
throw std::runtime_error(std::string("Couldn't find file at path: ") + filename); | ||
} | ||
|
||
fseek(fd, 0, SEEK_END); | ||
size_t file_size = ftell(fd); | ||
fseek(fd, 0, SEEK_SET); | ||
double num_frames_frac = (double) file_size / (this->num_bins * 2 * sizeof(float)); | ||
printf("FFTBuffer: File size %zu bytes, %.2f frames\n", file_size, num_frames_frac); | ||
if (num_frames_frac != (int) num_frames_frac) | ||
{ | ||
throw std::runtime_error("Error: Not an integer number of frames (found " + std::to_string(num_frames) + " frames)"); | ||
} | ||
this->num_frames = (unsigned int) num_frames_frac; | ||
|
||
/*-------------------------------------------------------------------------------- | ||
* If the AudioGraph has been instantiated, populate the buffer's sample | ||
* rate and duration. Otherwise, zero them. | ||
*-------------------------------------------------------------------------------*/ | ||
if (shared_graph) | ||
{ | ||
this->sample_rate = shared_graph->get_sample_rate(); | ||
this->duration = (this->num_frames * this->hop_size) / this->sample_rate; | ||
} | ||
else | ||
{ | ||
this->sample_rate = 0; | ||
this->duration = 0; | ||
} | ||
|
||
this->resize(num_frames); | ||
} | ||
|
||
FFTBuffer::~FFTBuffer() | ||
{ | ||
if (this->data) | ||
{ | ||
delete this->data[0]; | ||
delete this->data; | ||
|
||
if (shared_graph) | ||
{ | ||
size_t num_bytes = this->get_total_num_values() * sizeof(sample); | ||
shared_graph->register_memory_dealloc(num_bytes); | ||
} | ||
} | ||
} | ||
|
||
void FFTBuffer::resize(int num_frames) | ||
{ | ||
if (this->data) | ||
{ | ||
delete this->data[0]; | ||
delete this->data; | ||
|
||
if (shared_graph) | ||
{ | ||
size_t num_bytes = this->get_total_num_values() * sizeof(sample); | ||
shared_graph->register_memory_dealloc(num_bytes); | ||
} | ||
} | ||
|
||
this->num_frames = num_frames; | ||
|
||
/*-------------------------------------------------------------------------------- | ||
* For use in numpy, memory allocation needs to be contiguous with a fixed | ||
* stride between vectors. Allocate as one block and set element indices | ||
* accordingly. | ||
*-------------------------------------------------------------------------------*/ | ||
if (num_frames) | ||
{ | ||
this->data = new sample *[this->num_frames](); | ||
|
||
sample *data_frames = new sample[this->get_total_num_values()](); | ||
for (unsigned int frame = 0; frame < this->num_frames; frame++) | ||
{ | ||
this->data[frame] = data_frames + frame * (this->num_bins * 2); | ||
} | ||
|
||
if (shared_graph) | ||
{ | ||
size_t num_bytes = this->get_total_num_values() * sizeof(sample); | ||
shared_graph->register_memory_alloc(num_bytes); | ||
} | ||
} | ||
else | ||
{ | ||
this->data = nullptr; | ||
} | ||
} | ||
|
||
float FFTBuffer::get_sample_rate() { return this->sample_rate; } | ||
|
||
void FFTBuffer::set_sample_rate(float sample_rate) { this->sample_rate = sample_rate; } | ||
|
||
unsigned long FFTBuffer::get_num_frames() { return this->num_frames; } | ||
|
||
std::string FFTBuffer::get_filename() { return this->filename; } | ||
|
||
unsigned int FFTBuffer::get_fft_size() { return this->fft_size; } | ||
|
||
unsigned int FFTBuffer::get_hop_size() { return this->hop_size; } | ||
|
||
float FFTBuffer::get_duration() { return this->duration; } | ||
|
||
unsigned long FFTBuffer::get_total_num_values() { return this->num_frames * this->num_bins * 2; } | ||
|
||
template class FFTBufferRefTemplate<FFTBuffer>; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters