yammer/src/c/yammer.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