parent
c3bf79d5ac
commit
3fab7f9efe
@ -1,372 +0,0 @@ |
||||
//
|
||||
// Created by frank on 2021/8/16.
|
||||
//
|
||||
|
||||
#include "execute_fft.h" |
||||
|
||||
#include <android/log.h> |
||||
#define LOG_TAG "execute_fft" |
||||
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, \ |
||||
__VA_ARGS__)) |
||||
|
||||
#define NB_BANDS 20 |
||||
#define BAR_DECREMENT .075f |
||||
|
||||
int open_visualizer(filter_sys_t *p_sys) |
||||
{ |
||||
if (p_sys == nullptr) |
||||
return -1; |
||||
|
||||
p_sys->i_channels = 1; |
||||
p_sys->i_prev_nb_samples = 0; |
||||
p_sys->p_prev_s16_buff = nullptr; |
||||
p_sys->wind_param = new window_param(); |
||||
|
||||
/* Fetch the FFT window parameters */ |
||||
window_get_param(p_sys->wind_param); |
||||
|
||||
/* Create the FIFO for the audio data. */ |
||||
vlc_queue_t *queue = vlc_queue_init(5); |
||||
p_sys->queue = *queue; |
||||
p_sys->dead = false; |
||||
|
||||
pthread_create (&p_sys->thread, nullptr, fft_thread, p_sys); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
block_t *filter_audio(filter_sys_t *p_sys, void *p_in_buf) |
||||
{ |
||||
return (block_t *) vlc_queue_push(&p_sys->queue, p_in_buf); |
||||
} |
||||
|
||||
void close_visualizer(filter_sys_t *p_filter) |
||||
{ |
||||
filter_sys_t *p_sys = p_filter; |
||||
vlc_queue_free(&p_sys->queue); |
||||
pthread_join(p_sys->thread, nullptr); |
||||
|
||||
if (p_sys->p_prev_s16_buff) { |
||||
delete [] (p_sys->p_prev_s16_buff); |
||||
} |
||||
if (p_sys->wind_param) { |
||||
delete (p_sys->wind_param); |
||||
} |
||||
if (p_sys->data) { |
||||
delete [] (p_sys->data); |
||||
} |
||||
if (p_sys->output) { |
||||
delete [] (p_sys->output); |
||||
} |
||||
delete (p_sys); |
||||
} |
||||
|
||||
static void *fft_thread(void *p_data) |
||||
{ |
||||
auto *p_sys = (filter_sys_t*)p_data; |
||||
block_t *block; |
||||
|
||||
float height[NB_BANDS] = {0}; |
||||
LOGE("start FFT thread..."); |
||||
|
||||
while ((block = (block_t *) vlc_queue_pop(&p_sys->queue))) |
||||
{ |
||||
LOGE("running FFT transform..."); |
||||
/* Horizontal scale for 20-band equalizer */ |
||||
const unsigned xscale[] = {0,1,2,3,4,5,6,7,8,11,15,20,27, |
||||
36,47,62,82,107,141,184,255}; |
||||
|
||||
fft_state *p_state = nullptr; /* internal FFT data */ |
||||
DEFINE_WIND_CONTEXT(wind_ctx); /* internal window data */ |
||||
|
||||
unsigned i, j; |
||||
float p_output[FFT_BUFFER_SIZE]; /* Raw FFT Result */ |
||||
int16_t p_buffer1[FFT_BUFFER_SIZE]; /* Buffer on which we perform
|
||||
the FFT (first channel) */ |
||||
int16_t p_dest[FFT_BUFFER_SIZE]; /* Adapted FFT result */ |
||||
auto *p_buffl = (float*)block->p_buffer; /* Original buffer */ |
||||
|
||||
int16_t *p_buffs; /* int16_t converted buffer */ |
||||
int16_t *p_s16_buff; /* int16_t converted buffer */ |
||||
|
||||
if (!block->i_nb_samples) { |
||||
LOGE("no samples yet..."); |
||||
goto release; |
||||
} |
||||
|
||||
/* Allocate the buffer only if the number of samples change */ |
||||
if (block->i_nb_samples != p_sys->i_prev_nb_samples) |
||||
{ |
||||
if (p_sys->p_prev_s16_buff) delete [] (p_sys->p_prev_s16_buff); |
||||
p_sys->p_prev_s16_buff = new int16_t [block->i_nb_samples * p_sys->i_channels]; |
||||
if (!p_sys->p_prev_s16_buff) |
||||
goto release; |
||||
p_sys->i_prev_nb_samples = block->i_nb_samples; |
||||
} |
||||
p_buffs = p_s16_buff = p_sys->p_prev_s16_buff; |
||||
|
||||
/* Convert the buffer to int16_t */ |
||||
for (i = block->i_nb_samples * p_sys->i_channels; i--;) |
||||
{ |
||||
union {float f; int32_t i;} u{}; |
||||
|
||||
u.f = *p_buffl + 384.f; |
||||
if (u.i > 0x43c07fff) |
||||
*p_buffs = 32767; |
||||
else if (u.i < 0x43bf8000) |
||||
*p_buffs = -32768; |
||||
else |
||||
*p_buffs = u.i - 0x43c00000; |
||||
|
||||
p_buffl++; p_buffs++; |
||||
} |
||||
p_state = visual_fft_init(); |
||||
if (!p_state) |
||||
{ |
||||
LOGE("unable to initialize FFT transform..."); |
||||
goto release; |
||||
} |
||||
if (!window_init(FFT_BUFFER_SIZE, p_sys->wind_param, &wind_ctx)) |
||||
{ |
||||
LOGE("unable to initialize FFT window..."); |
||||
goto release; |
||||
} |
||||
p_buffs = p_s16_buff; |
||||
for (i = 0 ; i < FFT_BUFFER_SIZE; i++) |
||||
{ |
||||
p_output[i] = 0; |
||||
p_buffer1[i] = *p_buffs; |
||||
|
||||
p_buffs += p_sys->i_channels; |
||||
if (p_buffs >= &p_s16_buff[block->i_nb_samples * p_sys->i_channels]) |
||||
p_buffs = p_s16_buff; |
||||
} |
||||
window_scale_in_place (p_buffer1, &wind_ctx); |
||||
fft_perform (p_buffer1, p_output, p_state); |
||||
|
||||
for (i = 0; i< FFT_BUFFER_SIZE; ++i) |
||||
p_dest[i] = p_output[i] * (2 ^ 16) |
||||
/ ((FFT_BUFFER_SIZE / 2 * 32768) ^ 2); |
||||
|
||||
for (i = 0 ; i < NB_BANDS; i++) |
||||
{ |
||||
/* Decrease the previous size of the bar. */ |
||||
height[i] -= BAR_DECREMENT; |
||||
if (height[i] < 0) |
||||
height[i] = 0; |
||||
|
||||
int y = 0; |
||||
/* We search the maximum on one scale
|
||||
to determine the current size of the bar. */ |
||||
for (j = xscale[i]; j < xscale[i + 1]; j++) |
||||
{ |
||||
if (p_dest[j] > y) |
||||
y = p_dest[j]; |
||||
} |
||||
/* Calculate the height of the bar */ |
||||
float new_height = y != 0 ? logf(y) * 0.4f : 0; |
||||
height[i] = new_height > height[i] |
||||
? new_height : height[i]; |
||||
} |
||||
|
||||
usleep(10*1000 /*block->i_pts + (block->i_length / 2)*/); |
||||
block->fft_callback.callback(p_dest); |
||||
|
||||
release: |
||||
window_close(&wind_ctx); |
||||
fft_close(p_state); |
||||
} |
||||
|
||||
return nullptr; |
||||
} |
||||
|
||||
|
||||
int init_visualizer(filter_sys_t *p_filter) |
||||
{ |
||||
if (p_filter == nullptr) |
||||
return -1; |
||||
|
||||
p_filter->i_channels = 1; |
||||
p_filter->i_prev_nb_samples = 0; |
||||
p_filter->p_prev_s16_buff = nullptr; |
||||
|
||||
p_filter->wind_param = new window_param(); |
||||
|
||||
/* Fetch the FFT window parameters */ |
||||
window_get_param(p_filter->wind_param); |
||||
|
||||
p_filter->data = nullptr; |
||||
p_filter->data_size = 0; |
||||
p_filter->nb_samples = 0; |
||||
#ifdef FIXED_FFT |
||||
p_filter->out_samples = 512; |
||||
#else |
||||
p_filter->out_samples = FFT_BUFFER_SIZE; |
||||
#endif |
||||
p_filter->output = new int8_t[p_filter->out_samples]; |
||||
if (!p_filter->output) return -1; |
||||
p_filter->data_size = MAX_FFT_SIZE; |
||||
p_filter->data = new uint8_t[MAX_FFT_SIZE]; |
||||
if (!p_filter->data) { |
||||
return -1; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
void release_visualizer(filter_sys_t *p_filter) |
||||
{ |
||||
if (!p_filter) return; |
||||
if (p_filter->p_prev_s16_buff) { |
||||
delete [] (p_filter->p_prev_s16_buff); |
||||
} |
||||
if (p_filter->wind_param) { |
||||
delete (p_filter->wind_param); |
||||
} |
||||
if (p_filter->data) { |
||||
delete [] (p_filter->data); |
||||
} |
||||
if (p_filter->output) { |
||||
delete [] (p_filter->output); |
||||
} |
||||
delete (p_filter); |
||||
} |
||||
|
||||
void fft_float(filter_sys_t *p_sys) |
||||
{ |
||||
int nb_samples = p_sys->nb_samples; |
||||
int out_samples = p_sys->out_samples; |
||||
|
||||
fft_state *p_state = nullptr; /* internal FFT data */ |
||||
DEFINE_WIND_CONTEXT(wind_ctx); /* internal window data */ |
||||
|
||||
unsigned i; |
||||
float p_output[out_samples]; /* Raw FFT Result */ |
||||
int16_t p_buffer1[out_samples]; /* Buffer on which we perform */ |
||||
auto *p_buffl = (float*)p_sys->data; /* Original buffer */ |
||||
|
||||
int16_t *p_buffs; /* int16_t converted buffer */ |
||||
int16_t *p_s16_buff; /* int16_t converted buffer */ |
||||
|
||||
if (!nb_samples) { |
||||
LOGE("no samples yet..."); |
||||
goto release; |
||||
} |
||||
|
||||
/* Allocate the buffer only if the number of samples change */ |
||||
if (nb_samples != p_sys->i_prev_nb_samples) { |
||||
if (p_sys->p_prev_s16_buff) delete [] (p_sys->p_prev_s16_buff); |
||||
p_sys->p_prev_s16_buff = new int16_t [nb_samples * p_sys->i_channels]; |
||||
if (!p_sys->p_prev_s16_buff) |
||||
goto release; |
||||
p_sys->i_prev_nb_samples = nb_samples; |
||||
} |
||||
p_buffs = p_s16_buff = p_sys->p_prev_s16_buff; |
||||
|
||||
/* Convert the buffer to int16_t */ |
||||
for (i = nb_samples * p_sys->i_channels; i--;) { |
||||
union {float f; int32_t i;} u{}; |
||||
|
||||
u.f = *p_buffl + 384.f; |
||||
if (u.i > 0x43c07fff) |
||||
*p_buffs = 32767; |
||||
else if (u.i < 0x43bf8000) |
||||
*p_buffs = -32768; |
||||
else |
||||
*p_buffs = u.i - 0x43c00000; |
||||
|
||||
p_buffl++; p_buffs++; |
||||
} |
||||
p_state = visual_fft_init(); |
||||
if (!p_state) { |
||||
LOGE("unable to initialize FFT transform..."); |
||||
goto release; |
||||
} |
||||
if (!window_init(out_samples, p_sys->wind_param, &wind_ctx)) { |
||||
LOGE("unable to initialize FFT window..."); |
||||
goto release; |
||||
} |
||||
p_buffs = p_s16_buff; |
||||
for (i = 0 ; i < out_samples; i++) |
||||
{ |
||||
p_output[i] = 0; |
||||
p_buffer1[i] = *p_buffs; |
||||
|
||||
p_buffs += p_sys->i_channels; |
||||
if (p_buffs >= &p_s16_buff[nb_samples * p_sys->i_channels]) |
||||
p_buffs = p_s16_buff; |
||||
} |
||||
window_scale_in_place (p_buffer1, &wind_ctx); |
||||
fft_perform (p_buffer1, p_output, p_state); |
||||
|
||||
for (i = 0; i < out_samples; ++i) { |
||||
int16_t temp = p_output[i] * (2 ^ 16) |
||||
/ ((out_samples / 2 * 32768) ^ 2); |
||||
|
||||
p_sys->output[i] = temp & 0xFF; |
||||
} |
||||
|
||||
release: |
||||
window_close(&wind_ctx); |
||||
fft_close(p_state); |
||||
} |
||||
|
||||
int doFft(uint8_t *fft, const uint8_t *waveform, int mCaptureSize) |
||||
{ |
||||
int32_t workspace[mCaptureSize >> 1]; |
||||
int32_t nonzero = 0; |
||||
|
||||
for (uint32_t i = 0; i < mCaptureSize; i += 2) { |
||||
workspace[i >> 1] = |
||||
((waveform[i] ^ 0x80) << 24) | ((waveform[i + 1] ^ 0x80) << 8); |
||||
nonzero |= workspace[i >> 1]; |
||||
} |
||||
|
||||
if (nonzero) { |
||||
fixed_fft_real(mCaptureSize >> 1, workspace); |
||||
} |
||||
|
||||
for (uint32_t i = 0; i < mCaptureSize; i += 2) { |
||||
short tmp = workspace[i >> 1] >> 21; |
||||
while (tmp > 127 || tmp < -128) tmp >>= 1; |
||||
fft[i] = tmp; |
||||
tmp = workspace[i >> 1]; |
||||
tmp >>= 5; |
||||
while (tmp > 127 || tmp < -128) tmp >>= 1; |
||||
fft[i + 1] = tmp; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
void fft_fixed(filter_sys_t *p_sys) |
||||
{ |
||||
int nb_samples = p_sys->nb_samples; |
||||
int out_samples = p_sys->out_samples; |
||||
|
||||
DEFINE_WIND_CONTEXT(wind_ctx); |
||||
|
||||
if (!nb_samples) { |
||||
LOGE("no samples yet..."); |
||||
goto release; |
||||
} |
||||
|
||||
if (!window_init(out_samples, p_sys->wind_param, &wind_ctx)) { |
||||
LOGE("unable to initialize FFT window..."); |
||||
goto release; |
||||
} |
||||
|
||||
window_scale_in_place ((int16_t *) (p_sys->data), &wind_ctx); |
||||
doFft((uint8_t *) p_sys->output, p_sys->data, out_samples); |
||||
|
||||
release: |
||||
window_close(&wind_ctx); |
||||
} |
||||
|
||||
void fft_once(filter_sys_t *p_sys) |
||||
{ |
||||
#ifdef FIXED_FFT |
||||
fft_fixed(p_sys); |
||||
#else |
||||
fft_float(p_sys); |
||||
#endif |
||||
} |
@ -1,66 +0,0 @@ |
||||
//
|
||||
// Created by frank on 2021/8/16.
|
||||
//
|
||||
|
||||
#ifndef EXECUTE_FFT_H |
||||
#define EXECUTE_FFT_H |
||||
|
||||
#include <math.h> |
||||
#include <unistd.h> |
||||
#include "fft.h" |
||||
#include "window.h" |
||||
#include "fixed_fft.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
#include "block_queue.h" |
||||
|
||||
#define MIN_FFT_SIZE 128 |
||||
#define MAX_FFT_SIZE 1024 |
||||
|
||||
#define FIXED_FFT 1 |
||||
|
||||
typedef struct |
||||
{ |
||||
pthread_t thread; |
||||
vlc_queue_t queue; |
||||
bool dead; |
||||
int i_channels; |
||||
int i_prev_nb_samples; |
||||
int16_t *p_prev_s16_buff; |
||||
|
||||
/* FFT window parameters */ |
||||
window_param *wind_param; |
||||
|
||||
uint8_t *data; |
||||
int data_size; |
||||
int nb_samples; |
||||
int8_t *output; |
||||
int out_samples; |
||||
} filter_sys_t; |
||||
|
||||
static void *fft_thread(void *); |
||||
|
||||
int open_visualizer(filter_sys_t *p_sys); |
||||
|
||||
block_t *filter_audio(filter_sys_t *p_sys, void *p_in_buf); |
||||
|
||||
void close_visualizer(filter_sys_t *p_filter); |
||||
|
||||
void fft_once(filter_sys_t *p_sys); |
||||
|
||||
int init_visualizer(filter_sys_t *p_sys); |
||||
|
||||
void release_visualizer(filter_sys_t *p_sys); |
||||
|
||||
void fft_float(filter_sys_t *p_sys); |
||||
|
||||
void fft_fixed(filter_sys_t *p_sys); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif //EXECUTE_FFT_H
|
@ -0,0 +1,220 @@ |
||||
//
|
||||
// Created by frank on 2021/8/16.
|
||||
//
|
||||
|
||||
#include "frank_visualizer.h" |
||||
|
||||
#include <android/log.h> |
||||
#define LOG_TAG "frank_visualizer" |
||||
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, \ |
||||
__VA_ARGS__)) |
||||
|
||||
|
||||
void short_to_float_array (const short *in, float *out, int len) { |
||||
for (int i = 0; i < len; ++i) { |
||||
out [i] = (float) (in [i] / (1.0 * 0x8000)) ; |
||||
} |
||||
} |
||||
|
||||
// float FFT algorithm
|
||||
void fft_float(filter_sys_t *p_sys) { |
||||
int nb_samples = p_sys->nb_samples; |
||||
int out_samples = p_sys->out_samples; |
||||
|
||||
fft_state *p_state = nullptr; /* internal FFT data */ |
||||
DEFINE_WIND_CONTEXT(wind_ctx); /* internal window data */ |
||||
|
||||
unsigned i; |
||||
float p_output[out_samples]; /* Raw FFT Result */ |
||||
int16_t p_buffer1[out_samples]; /* Buffer on which we perform the FFT*/ |
||||
float *p_buffl; |
||||
if (p_sys->convert_to_float) { |
||||
float p_buff[out_samples]; |
||||
short_to_float_array((const short *) p_sys->data, p_buff, out_samples); |
||||
p_buffl = p_buff; |
||||
} else { |
||||
p_buffl = (float *) (p_sys->data); |
||||
} |
||||
|
||||
int16_t *p_buffs; /* int16_t converted buffer */ |
||||
int16_t *p_s16_buff; /* int16_t converted buffer */ |
||||
|
||||
if (!nb_samples) { |
||||
LOGE("no samples yet..."); |
||||
goto release; |
||||
} |
||||
|
||||
/* Allocate the buffer only if the number of samples change */ |
||||
if (nb_samples != p_sys->i_prev_nb_samples) { |
||||
if (p_sys->p_prev_s16_buff) delete [] (p_sys->p_prev_s16_buff); |
||||
p_sys->p_prev_s16_buff = new int16_t [nb_samples * p_sys->i_channels]; |
||||
if (!p_sys->p_prev_s16_buff) |
||||
goto release; |
||||
p_sys->i_prev_nb_samples = nb_samples; |
||||
} |
||||
p_buffs = p_s16_buff = p_sys->p_prev_s16_buff; |
||||
|
||||
/* Convert the buffer to int16_t */ |
||||
for (i = nb_samples * p_sys->i_channels; i--;) { |
||||
union {float f; int32_t i;} u{}; |
||||
|
||||
u.f = *p_buffl + 384.f; |
||||
if (u.i > 0x43c07fff) |
||||
*p_buffs = 32767; |
||||
else if (u.i < 0x43bf8000) |
||||
*p_buffs = -32768; |
||||
else |
||||
*p_buffs = u.i - 0x43c00000; |
||||
|
||||
p_buffl++; p_buffs++; |
||||
} |
||||
p_state = visual_fft_init(); |
||||
if (!p_state) { |
||||
LOGE("unable to initialize FFT transform..."); |
||||
goto release; |
||||
} |
||||
if (!window_init(out_samples, p_sys->wind_param, &wind_ctx)) { |
||||
LOGE("unable to initialize FFT window..."); |
||||
goto release; |
||||
} |
||||
p_buffs = p_s16_buff; |
||||
for (i = 0 ; i < out_samples; i++) { |
||||
p_output[i] = 0; |
||||
p_buffer1[i] = *p_buffs; |
||||
|
||||
p_buffs += p_sys->i_channels; |
||||
if (p_buffs >= &p_s16_buff[nb_samples * p_sys->i_channels]) |
||||
p_buffs = p_s16_buff; |
||||
} |
||||
window_scale_in_place (p_buffer1, &wind_ctx); |
||||
fft_perform (p_buffer1, p_output, p_state); |
||||
|
||||
for (i = 0; i < out_samples; ++i) { |
||||
int16_t temp = p_output[i] * (2 ^ 16) |
||||
/ ((out_samples / 2 * 32768) ^ 2); |
||||
p_sys->output[i] = temp & 0xFF; |
||||
} |
||||
|
||||
release: |
||||
window_close(&wind_ctx); |
||||
fft_close(p_state); |
||||
} |
||||
|
||||
int fft_fixed_internal(uint8_t *fft, const uint8_t *waveform, int mCaptureSize) { |
||||
int32_t workspace[mCaptureSize >> 1]; |
||||
int32_t nonzero = 0; |
||||
|
||||
for (uint32_t i = 0; i < mCaptureSize; i += 2) { |
||||
workspace[i >> 1] = |
||||
((waveform[i] ^ 0x80) << 24) | ((waveform[i + 1] ^ 0x80) << 8); |
||||
nonzero |= workspace[i >> 1]; |
||||
} |
||||
|
||||
if (nonzero) { |
||||
fixed_fft_real(mCaptureSize >> 1, workspace); |
||||
} |
||||
|
||||
for (uint32_t i = 0; i < mCaptureSize; i += 2) { |
||||
short tmp = workspace[i >> 1] >> 21; |
||||
while (tmp > 127 || tmp < -128) tmp >>= 1; |
||||
fft[i] = tmp; |
||||
tmp = workspace[i >> 1]; |
||||
tmp >>= 5; |
||||
while (tmp > 127 || tmp < -128) tmp >>= 1; |
||||
fft[i + 1] = tmp; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
// fixed FFT algorithm
|
||||
void fft_fixed(filter_sys_t *p_sys) { |
||||
int nb_samples = p_sys->nb_samples; |
||||
int out_samples = p_sys->out_samples; |
||||
|
||||
DEFINE_WIND_CONTEXT(wind_ctx); |
||||
if (!nb_samples) { |
||||
LOGE("no samples yet..."); |
||||
goto release; |
||||
} |
||||
|
||||
if (!window_init(out_samples, p_sys->wind_param, &wind_ctx)) { |
||||
LOGE("unable to initialize FFT window..."); |
||||
goto release; |
||||
} |
||||
|
||||
window_scale_in_place ((int16_t *) p_sys->data, &wind_ctx); |
||||
fft_fixed_internal((uint8_t *) p_sys->output, p_sys->data, out_samples); |
||||
|
||||
release: |
||||
window_close(&wind_ctx); |
||||
} |
||||
|
||||
FrankVisualizer::FrankVisualizer() { |
||||
LOGE("FrankVisualizer init..."); |
||||
} |
||||
|
||||
FrankVisualizer::~FrankVisualizer() { |
||||
LOGE("FrankVisualizer release..."); |
||||
} |
||||
|
||||
void FrankVisualizer::fft_run() { |
||||
mFftLock.lock(); |
||||
filter_sys_t *p_sys = fft_context; |
||||
#ifdef FIXED_FFT |
||||
fft_fixed(p_sys); |
||||
#else |
||||
fft_float(p_sys); |
||||
#endif |
||||
mFftLock.unlock(); |
||||
} |
||||
|
||||
int FrankVisualizer::init_visualizer() { |
||||
fft_context = new filter_sys_t(); |
||||
filter_sys_t *p_filter = fft_context; |
||||
if (!p_filter) |
||||
return -1; |
||||
|
||||
p_filter->convert_to_float = false; |
||||
p_filter->i_channels = 1; |
||||
p_filter->i_prev_nb_samples = 0; |
||||
p_filter->p_prev_s16_buff = nullptr; |
||||
p_filter->data = nullptr; |
||||
p_filter->data_size = 0; |
||||
p_filter->nb_samples = 0; |
||||
#ifdef FIXED_FFT |
||||
p_filter->out_samples = 512; |
||||
#else |
||||
p_filter->out_samples = FFT_BUFFER_SIZE; |
||||
#endif |
||||
|
||||
p_filter->wind_param = new window_param(); |
||||
/* Fetch the FFT window parameters */ |
||||
window_get_param(p_filter->wind_param); |
||||
p_filter->data_size = MAX_FFT_SIZE; |
||||
p_filter->data = new uint8_t[MAX_FFT_SIZE]; |
||||
memset(p_filter->data, 0, MAX_FFT_SIZE); |
||||
p_filter->output = new int8_t[p_filter->out_samples]; |
||||
memset(p_filter->output, 0, p_filter->out_samples); |
||||
return 0; |
||||
} |
||||
|
||||
void FrankVisualizer::release_visualizer() { |
||||
mFftLock.lock(); |
||||
filter_sys_t *p_filter = fft_context; |
||||
if (!p_filter) return; |
||||
if (p_filter->p_prev_s16_buff) { |
||||
delete [] (p_filter->p_prev_s16_buff); |
||||
} |
||||
if (p_filter->wind_param) { |
||||
delete (p_filter->wind_param); |
||||
} |
||||
if (p_filter->data) { |
||||
delete [] (p_filter->data); |
||||
} |
||||
if (p_filter->output) { |
||||
delete [] (p_filter->output); |
||||
} |
||||
delete p_filter; |
||||
mFftLock.unlock(); |
||||
} |
@ -0,0 +1,54 @@ |
||||
//
|
||||
// Created by frank on 2021/8/16.
|
||||
//
|
||||
|
||||
#ifndef FRANK_VISUALIZER_H |
||||
#define FRANK_VISUALIZER_H |
||||
|
||||
#include <math.h> |
||||
#include <mutex> |
||||
|
||||
#include "fft.h" |
||||
#include "window.h" |
||||
#include "fixed_fft.h" |
||||
|
||||
#define MIN_FFT_SIZE 128 |
||||
#define MAX_FFT_SIZE 1024 |
||||
|
||||
#define FIXED_FFT 1 |
||||
|
||||
typedef struct |
||||
{ |
||||
bool convert_to_float; |
||||
int i_channels; |
||||
int i_prev_nb_samples; |
||||
int16_t *p_prev_s16_buff; |
||||
|
||||
window_param *wind_param; |
||||
|
||||
uint8_t *data; |
||||
int data_size; |
||||
int nb_samples; |
||||
int8_t *output; |
||||
int out_samples; |
||||
} filter_sys_t; |
||||
|
||||
|
||||
class FrankVisualizer { |
||||
|
||||
public: |
||||
FrankVisualizer(); |
||||
~FrankVisualizer(); |
||||
|
||||
std::mutex mFftLock; |
||||
|
||||
filter_sys_t *fft_context = nullptr; |
||||
|
||||
void fft_run(); |
||||
|
||||
int init_visualizer(); |
||||
|
||||
void release_visualizer(); |
||||
}; |
||||
|
||||
#endif //FRANK_VISUALIZER_H
|
Loading…
Reference in new issue