Skip to content

[cute_sound] pitched sounds get "stuck" and do not stop playing #426

@jdah

Description

@jdah

When using the latest cute_sound.h, some pitched sounds (maybe all?) do not stop playing (are still marked as active even though there is no sound).

minimal example:

#include <SDL3/SDL.h>

#define CUTE_SOUND_IMPLEMENTATION
#include "cute_sound.h"

#include <stdio.h>
#include <stdint.h>

int main(int argc, char *argv[]) {
    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
    SDL_Window *window = SDL_CreateWindow(
        "test",
        800,
        600,
        0
    );
    SDL_RaiseWindow(window);
    cs_init(44100, NULL);
    cs_set_global_volume(1);

    cs_audio_source_t *src = cs_load_wav("sound.wav", NULL);
    const cs_playing_sound_t sound1 =
        cs_play_sound(
            src,
            (cs_sound_params_t) { .volume = 1.0f, .pan = 0.5f, .pitch = 1.1f });
    const cs_playing_sound_t sound2 =
        cs_play_sound(
            src,
            (cs_sound_params_t) { .volume = 1.0f, .pan = 0.5f, .pitch = 1.0f });

    uint64_t previous = SDL_GetPerformanceCounter();
    uint64_t frequency = SDL_GetPerformanceFrequency();
    int running = 1;
    SDL_Event event;
    while (running) {
        uint64_t current = SDL_GetPerformanceCounter();
        double dt = (double)(current - previous) / (double)frequency;
        previous = current;

        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_EVENT_QUIT) {
                running = 0;
            }
        }

        printf("1 playing: %d / 2 playing: %d\n",
               cs_sound_is_active(sound1) ? 1 : 0,
               cs_sound_is_active(sound2) ? 1 : 0);
        cs_update(dt);
        SDL_Delay(16);
    }

    cs_shutdown();
    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}

sound1 continues to play after stopping (pitch = 1.1) and sound2 stops as normal (pitch = 1.0).

Some investigation indicates that the issue is around cute_sound.h:1458:

	// For looped pitched sounds, CS_WRAP_SAMPLE handles wraparound so we can
	// mix the full buffer. For non-looped or non-pitched sounds, we must clamp.
	if (!playing->looped || !pitched) {
		if (playing->pitch >= 0) {
			double input_remaining = (double)audio->sample_count - playing->sample_index;
			int max_output = (int)(input_remaining / playing->pitch);
                         // this will keep printing ("max_output is 0 (12729 - 12728.100)"
                        printf("max_output is %d (%d - %.3f)\n", max_output, audio->sample_count, playing->sample_index);
			if (samples_to_write > max_output) {
				samples_to_write = max_output;
			}
		} else {
			double input_remaining = playing->sample_index;
			int max_output = (int)(input_remaining / -playing->pitch);
			if (samples_to_write > max_output) {
				samples_to_write = max_output;
			}
		}

since samples_to_write always goes to 0 and at_end is never set.

Throwing in this (garbage) code before the check for samples_to_write <= 0 (cute_sound.h:1470) seems to fix things, though I don't know if it breaks anything else:

  double diff = (double) audio->sample_count - playing->sample_index;
  if (diff < 0) { diff *= -1; }
  if (diff < 1.0) {
       cs_stop_sound_internal(playing);
       break;
  }

Hope that helps on a fix. The test sound is attached.

EDIT: whoops, added the attachment. Github won't let me upload raw .wav files and needs them in a .zip?

sound.wav.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions