131 lines
3.9 KiB
C
131 lines
3.9 KiB
C
/**
|
|
* Copyright (C) 2023 Skylar Widulski
|
|
*
|
|
* This file is part of Yammer.
|
|
*
|
|
* Yammer is free software: you can redistribute it and/or modify it under the
|
|
* terms of the GNU General Public License as published by the Free Software
|
|
* Foundation, either version 3 of the License, or (at your option) any later
|
|
* version.
|
|
*
|
|
* Yammer is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with
|
|
* Yammer. If not, see <https://www.gnu.org/licenses/>.
|
|
*
|
|
* @file yammer.c
|
|
* @brief C library for Yammer
|
|
* @details Library that wraps around other C libraries for easier access in
|
|
* Guile.
|
|
*/
|
|
|
|
#include "yammer.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
|
|
|
|
#ifdef USE_FFTW
|
|
|
|
/**
|
|
* @brief Initializes the FFTW plan
|
|
* @details This function initializes the FFTW plan for the DFT. It allocates
|
|
* memory for the input and output pointers, and creates the plan.
|
|
* @param vsize The size of the input pointer
|
|
* @return The FFTW plan
|
|
* @note The caller is responsible for freeing the plan
|
|
*/
|
|
fftw_plan init_plan(int vsize) {
|
|
// Allocate memory for the input and output arrays
|
|
double* in = fftw_malloc(sizeof(double) * vsize);
|
|
fftw_complex* out = fftw_malloc(sizeof(fftw_complex) * vsize);
|
|
|
|
// Create the FFTW plan
|
|
fftw_plan p = fftw_plan_dft_r2c_1d(vsize, in, out, FFTW_ESTIMATE);
|
|
|
|
// Free the input and output arrays as they are not needed anymore
|
|
// The plan has already been created and it's the only thing we need to keep
|
|
fftw_free(in);
|
|
fftw_free(out);
|
|
|
|
// Return the plan
|
|
return p;
|
|
}
|
|
|
|
/**
|
|
* @brief Performs the DFT
|
|
* @details This function performs the DFT on the input pointer. It allocates
|
|
* memory for the output pointer, and then copies the result of the DFT into it.
|
|
* @param plan The FFTW plan
|
|
* @param ins The input pointer
|
|
* @param len The length of the input pointer
|
|
* @return The output pointer
|
|
* @note The caller is responsible for freeing the output pointer
|
|
*/
|
|
short int* do_dft(fftw_plan plan, short int* ins, int len) {
|
|
// Calculate the length of the result
|
|
int result_len = len / 2 + 1;
|
|
|
|
// Allocate memory for the input and output arrays
|
|
double* in = fftw_malloc(sizeof(double) * len);
|
|
short int* outs = malloc(sizeof(short int) * result_len);
|
|
fftw_complex* out = fftw_malloc(sizeof(fftw_complex) * result_len);
|
|
|
|
// Copy the input data to the input array
|
|
for (int i = 0; i < len; i++) {
|
|
in[i] = (double)ins[i];
|
|
}
|
|
|
|
// Execute the FFTW plan
|
|
fftw_execute_dft_r2c(plan, in, out);
|
|
|
|
// Calculate the magnitude of the DFT and store it in the output array
|
|
for (int i = 0; i < result_len; i++) {
|
|
outs[i] = (short int)sqrt(out[i][0] * out[i][0] +
|
|
out[i][1] * out[i][1]);
|
|
// Apply a scaling factor to the output
|
|
outs[i] *= (log2(2 + i) * (100.0 / result_len));
|
|
}
|
|
|
|
// Free the input and output arrays as they are not needed anymore
|
|
fftw_free(in);
|
|
fftw_free(out);
|
|
|
|
// Return the output array
|
|
return outs;
|
|
}
|
|
|
|
#endif // USE_FFTW
|
|
|
|
|
|
#ifdef USE_PULSE
|
|
|
|
pa_simple* make_pa_simple(unsigned int bitrate, char* dev, int latency) {
|
|
pa_sample_spec ss = {
|
|
.format = PA_SAMPLE_S16NE,
|
|
.channels = 2,
|
|
.rate = bitrate
|
|
};
|
|
|
|
pa_buffer_attr attr;
|
|
attr.maxlength = (uint32_t) -1;
|
|
attr.tlength = (uint32_t) -1;
|
|
attr.prebuf = (uint32_t) -1;
|
|
attr.minreq = (uint32_t) -1;
|
|
attr.fragsize = latency;
|
|
|
|
return pa_simple_new(NULL, "Yammer", PA_STREAM_RECORD, dev,
|
|
"Audio Visualizer", &ss, NULL, &attr, NULL);
|
|
}
|
|
|
|
short int* read_from_pa(pa_simple* s, size_t bytes) {
|
|
short int* buf = malloc(sizeof(short int) * bytes);
|
|
pa_simple_read(s, buf, sizeof(short int) * bytes, NULL);
|
|
return buf;
|
|
}
|
|
|
|
#endif // USE_PULSE
|