Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: sample playback — restore pointer swap, don't kill voices on load

The previous fix (kill all voices + memcpy under lock) prevented
crashes but also prevented playback — every loadData call killed
active voices and held the lock too long for the audio callback.

Restore the back-buffer swap approach: write to sample_buf_back
without lock, then swap pointers under a brief lock. The audio
callback's trylock skips at most one 5ms period during the swap.
No voices are killed, playback continues uninterrupted.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+9 -10
+9 -10
fedac/native/src/audio.c
··· 1297 1297 } 1298 1298 1299 1299 void audio_sample_load_data(ACAudio *audio, const float *data, int len, unsigned int rate) { 1300 - if (!audio || !data || len <= 0 || !audio->sample_buf) return; 1300 + if (!audio || !data || len <= 0 || !audio->sample_buf_back) return; 1301 1301 if (len > audio->sample_max_len) len = audio->sample_max_len; 1302 - // Kill all active sample voices first — prevents reading during write 1302 + // Write to back buffer (only JS thread writes here — safe without lock) 1303 + memcpy(audio->sample_buf_back, data, len * sizeof(float)); 1304 + if (len < audio->sample_max_len) 1305 + memset(audio->sample_buf_back + len, 0, (audio->sample_max_len - len) * sizeof(float)); 1306 + // Swap pointers under lock — audio callback checks sample_loading flag 1303 1307 pthread_mutex_lock(&audio->lock); 1304 - for (int i = 0; i < AUDIO_MAX_SAMPLE_VOICES; i++) 1305 - audio->sample_voices[i].active = 0; 1306 - audio->sample_len = 0; // prevent audio callback from reading 1307 - __sync_synchronize(); 1308 - // Now safe to write — no readers 1309 - memcpy(audio->sample_buf, data, len * sizeof(float)); 1310 - if (len < audio->sample_max_len) 1311 - memset(audio->sample_buf + len, 0, (audio->sample_max_len - len) * sizeof(float)); 1308 + float *tmp = audio->sample_buf; 1309 + audio->sample_buf = audio->sample_buf_back; 1310 + audio->sample_buf_back = tmp; 1312 1311 audio->sample_len = len; 1313 1312 if (rate > 0) audio->sample_rate = rate; 1314 1313 __sync_synchronize();