Allow loading the entire audio file at vsjack_open() time,

get the actual oversampling, to allocate the sample space.
This commit is contained in:
Linus Torvalds 2025-07-13 15:03:07 +02:00 committed by Holger Vogt
parent dbb81ae1e7
commit 6e9e5f7d80
4 changed files with 74 additions and 72 deletions

View File

@ -13,13 +13,14 @@
#define VS_RESAMPLING_CHUNK 1024
#include "ngspice/ngspice.h"
#include "vsjack.h"
extern char* inp_pathresolve(const char* name);
#define MAX_D 6
static char* (sources[MAX_D]);
static SNDFILE* m_sndfile[MAX_D];
static int m_channel[MAX_D]; //< channel to be used in src-file
static int m_channels[MAX_D]; //< number of channles in src-file
static uint32_t m_samplerate[MAX_D]; //< samplerate of source
static uint32_t m_frames[MAX_D]; //< duration of source in frames
@ -29,8 +30,7 @@ static float* (interleaved[MAX_D]); //< internal soundfile buffer
#ifdef HAVE_SRC
#include <samplerate.h>
static double src_ratio = 64.0;
#define SRC_RATIO (src_ratio)
static double src_ratio[MAX_D];
static SRC_STATE* rabbit[MAX_D];
static int rabbit_err[MAX_D];
static float* (resampled[MAX_D]); //< internal soundfile buffer
@ -38,7 +38,7 @@ static uint32_t input_frames_used[MAX_D];
static uint32_t output_frames_generated[MAX_D];
#endif
void vsjack_initialize(void) {
static void vsjack_initialize(void) {
int d;
for (d = 0; d < MAX_D; d++) {
m_sndfile[d] = NULL;
@ -46,19 +46,16 @@ void vsjack_initialize(void) {
#ifdef HAVE_SRC
resampled[d] = NULL;
#endif
sources[d] = NULL;
}
sources[0] = strdup("/tmp/test.wav");
sources[1] = strdup("/tmp/test1.wav");
}
void realloc_sf(int d, uint32_t buffersize) {
static void realloc_sf(int d, uint32_t buffersize) {
if (interleaved[d]) free(interleaved[d]);
interleaved[d] = (float*)calloc(m_channels[d] * buffersize, sizeof(float));
}
#ifdef HAVE_SRC
void realloc_src(int d, uint32_t buffersize) {
static void realloc_src(int d, uint32_t buffersize) {
if (resampled[d]) free(resampled[d]);
resampled[d] = (float*)calloc(m_channels[d] * buffersize, sizeof(float));
}
@ -75,8 +72,8 @@ void closefile_sf(int d) {
}
#endif
int openfile_sf(int d, char* filename) {
uint32_t nframes;
static int openfile_sf(int d, char* filename, uint32_t channel, double oversampling) {
int nframes;
SF_INFO sfinfo;
if (!m_sndfile[d])
sf_close(m_sndfile[d]);
@ -102,17 +99,22 @@ int openfile_sf(int d, char* filename) {
return (-1);
}
nframes = sfinfo.frames;
if (channel >= sfinfo.channels) {
fprintf(stderr, "Error: Audio file does not have channel %d (0-%d)\n", channel, sfinfo.channels-1);
return (-1);
}
m_channel[d] = channel;
m_channels[d] = sfinfo.channels;
m_samplerate[d] = sfinfo.samplerate;
m_frames[d] = nframes;
realloc_sf(d, nframes);
#ifdef HAVE_SRC
SRC_DATA src_data;
realloc_src(d, nframes * SRC_RATIO);
src_ratio[d] = oversampling;
realloc_src(d, nframes * oversampling);
rabbit[d] = src_new(SRC_SINC_BEST_QUALITY, m_channels[d], &(rabbit_err[d]));
src_set_ratio(rabbit[d], SRC_RATIO);
src_set_ratio(rabbit[d], oversampling);
src_reset(rabbit[d]);
output_frames_generated[d] = 0;
input_frames_used[d] = 0;
@ -127,7 +129,8 @@ int openfile_sf(int d, char* filename) {
return (0);
}
double get_value(int d, double time, int channel) {
static double get_value(int d, double time) {
uint32_t channel = m_channel[d];
uint32_t nframes = m_frames[d];
double sample_fp = time * ((double)m_samplerate[d]);
uint32_t sample = (uint32_t)floor(sample_fp);
@ -135,6 +138,7 @@ double get_value(int d, double time, int channel) {
if (sample >= nframes) return (0.0);
#ifdef HAVE_SRC
double SRC_RATIO = src_ratio[d];
sample_fp *= SRC_RATIO;
sample = (uint32_t)floor(sample_fp);
@ -201,32 +205,24 @@ double get_value(int d, double time, int channel) {
* "public" functions
*/
double vsjack_get_value(int d, double time, double time_offset, int channel, double oversampling) {
double vsjack_get_value(int d, double time, double time_offset) {
assert(d >= 0 && d < MAX_D);
if (m_sndfile[d] == NULL) return (0.0); // FIXME
if (oversampling > 0) src_ratio = oversampling;
double value = get_value(d, time + time_offset, channel);
double value = get_value(d, time + time_offset);
return (value);
}
void vsjack_set_file(int d, char* fn) {
assert(d >= 0 && d < MAX_D);
if (sources[d] != NULL) free(sources[d]);
sources[d] = strdup(fn);
}
int vsjack_open(int d) {
int vsjack_open(int d, char *file, int channel, double oversampling) {
static int initialized = 0;
if (!initialized) {
initialized = 1;
vsjack_initialize();
}
if (d == -1) return -1;// initialize only
assert(d >= 0 && d < MAX_D);
assert(sources[d] != NULL);
if (openfile_sf(d, sources[d])) {
fprintf(stderr, "Error: Could not open or read '%s'\n", sources[d]);
if (openfile_sf(d, file, channel, oversampling)) {
fprintf(stderr, "Error: Could not open or read '%s'\n", file);
controlled_exit(1);
}
return (d);

View File

@ -1,4 +1,3 @@
double vsjack_get_value (int, double, double, int, double);
int vsjack_open (int);
void vsjack_set_file (int, char*);
double vsjack_get_value (int, double time, double time_offset);
int vsjack_open (int, char *file, int channel, double oversampling);

View File

@ -425,7 +425,7 @@ VNoi3 3 0 DC 0 TRNOISE(0 0 0 0 15m 22u 50u) : generate RTS noise
break;
case SOUND: {
value = here->VSRCcoeffs[2] * vsjack_get_value((int)here->VSRCcoeffs[0], time, here->VSRCcoeffs[3], (int)rint(here->VSRCcoeffs[4]), rint(here->VSRCcoeffs[5]));
value = here->VSRCcoeffs[2] * vsjack_get_value((int)here->VSRCcoeffs[0], time, here->VSRCcoeffs[3]);
value += here->VSRCcoeffs[1];
}
break;

View File

@ -295,18 +295,25 @@ VSRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
break;
case VSRC_SOUND: {
int id, channel;
double oversampling;
here->VSRCfunctionType = SOUND;
here->VSRCfuncTGiven = TRUE;
copy_coeffs(here, value);
here->VSRCcoeffsGiven = TRUE;
vsjack_open(-1); // initialize
if (jfile) {
vsjack_set_file((int)rint(here->VSRCcoeffs[0]), jfile);
tfree(jfile);
if (!jfile) {
fprintf(stderr, "Warning! Need filename for sound input");
return(E_BADPARM);
}
if (value->v.numValue != 6)
if (value->v.numValue != 6) {
fprintf(stderr, "Warning! invalid jack args: %i\nFormat: jack(id v_off v_mult t_off channel oversampling)", value->v.numValue);
vsjack_open((int)rint(here->VSRCcoeffs[0]));
return (E_BADPARM);
}
id = (int)rint(here->VSRCcoeffs[0]);
channel = (int)rint(here->VSRCcoeffs[4]);
oversampling = here->VSRCcoeffs[5];
vsjack_open(id, jfile, channel, oversampling);
tfree(jfile);
}
break;