diff --git a/fs.c b/fs.c index acf46b4..ef9a515 100644 --- a/fs.c +++ b/fs.c @@ -74,6 +74,19 @@ static void* autosave_thread_func(void *arg) { continue; } + // Deep-copy the audio buffers to avoid race conditions + float *buffer_copies[MAX_CLIPS] = {NULL}; + for (int i = 0; i < MAX_CLIPS; i++) { + if (state.clips[i].buffer != NULL && state.clips[i].buffer_size > 0) { + buffer_copies[i] = (float *)malloc(state.clips[i].buffer_size * sizeof(float)); + if (buffer_copies[i]) { + memcpy(buffer_copies[i], state.clips[i].buffer, state.clips[i].buffer_size * sizeof(float)); + // Temporarily point to our copy + state.clips[i].buffer = buffer_copies[i]; + } + } + } + // Generate autosave filename with timestamp char filename[512]; time_t t = time(NULL); @@ -87,6 +100,14 @@ static void* autosave_thread_func(void *arg) { fs_save_project(filename, &state); last_autosave_time = now; + // Free the buffer copies + for (int i = 0; i < MAX_CLIPS; i++) { + if (buffer_copies[i]) { + free(buffer_copies[i]); + buffer_copies[i] = NULL; + } + } + // Remove old autosaves (keep last 10) DIR *d = opendir(AUTOSAVE_DIR); if (d) { diff --git a/wav_io.c b/wav_io.c index 2ff6f31..4e5b825 100644 --- a/wav_io.c +++ b/wav_io.c @@ -3,6 +3,9 @@ #include #include #include +#include + +static pthread_mutex_t wav_io_mutex = PTHREAD_MUTEX_INITIALIZER; // WAV file header structures (little-endian) typedef struct { @@ -55,8 +58,13 @@ static uint32_t read_le32(const unsigned char *buf) { int save_wav_float(const char *filename, const float *buffer, size_t num_samples, unsigned int sample_rate) { if (!filename || !buffer || num_samples == 0) return -1; + pthread_mutex_lock(&wav_io_mutex); + FILE *f = fopen(filename, "wb"); - if (!f) return -1; + if (!f) { + pthread_mutex_unlock(&wav_io_mutex); + return -1; + } // Calculate sizes uint32_t data_size = (uint32_t)(num_samples * sizeof(float)); @@ -85,24 +93,32 @@ int save_wav_float(const char *filename, const float *buffer, size_t num_samples fwrite(buffer, sizeof(float), num_samples, f); fclose(f); + pthread_mutex_unlock(&wav_io_mutex); return 0; } int load_wav_float(const char *filename, float **buffer, size_t *num_samples, unsigned int *sample_rate) { if (!filename || !buffer || !num_samples || !sample_rate) return -1; + pthread_mutex_lock(&wav_io_mutex); + FILE *f = fopen(filename, "rb"); - if (!f) return -1; + if (!f) { + pthread_mutex_unlock(&wav_io_mutex); + return -1; + } // Read RIFF header unsigned char header[12]; if (fread(header, 1, 12, f) != 12) { fclose(f); + pthread_mutex_unlock(&wav_io_mutex); return -1; } if (memcmp(header, "RIFF", 4) != 0 || memcmp(header + 8, "WAVE", 4) != 0) { fclose(f); + pthread_mutex_unlock(&wav_io_mutex); return -1; } @@ -143,6 +159,7 @@ int load_wav_float(const char *filename, float **buffer, size_t *num_samples, un data_buffer = (float *)calloc(num_frames, sizeof(float)); if (!data_buffer) { fclose(f); + pthread_mutex_unlock(&wav_io_mutex); return -1; } @@ -154,12 +171,14 @@ int load_wav_float(const char *filename, float **buffer, size_t *num_samples, un if (!temp) { free(data_buffer); fclose(f); + pthread_mutex_unlock(&wav_io_mutex); return -1; } if (fread(temp, 1, read_size, f) != read_size) { free(temp); free(data_buffer); fclose(f); + pthread_mutex_unlock(&wav_io_mutex); return -1; } // Mix to mono if stereo @@ -183,12 +202,14 @@ int load_wav_float(const char *filename, float **buffer, size_t *num_samples, un if (!temp) { free(data_buffer); fclose(f); + pthread_mutex_unlock(&wav_io_mutex); return -1; } if (fread(temp, 1, read_size, f) != read_size) { free(temp); free(data_buffer); fclose(f); + pthread_mutex_unlock(&wav_io_mutex); return -1; } // Convert to float and mix to mono @@ -210,6 +231,7 @@ int load_wav_float(const char *filename, float **buffer, size_t *num_samples, un // Unsupported format free(data_buffer); fclose(f); + pthread_mutex_unlock(&wav_io_mutex); return -1; } @@ -217,6 +239,7 @@ int load_wav_float(const char *filename, float **buffer, size_t *num_samples, un *num_samples = num_frames; *sample_rate = sample_rate_val; fclose(f); + pthread_mutex_unlock(&wav_io_mutex); return 0; } else { // Skip unknown chunk @@ -227,5 +250,6 @@ int load_wav_float(const char *filename, float **buffer, size_t *num_samples, un // If we get here, we didn't find data if (data_buffer) free(data_buffer); fclose(f); + pthread_mutex_unlock(&wav_io_mutex); return -1; }