|
| 1 | +import wave |
1 | 2 | from pathlib import Path |
2 | 3 |
|
3 | 4 | import pytest |
| 5 | +from pyglet.media.codecs.base import StaticSource, StreamingSource |
| 6 | +from pyglet.media.codecs.wave import WAVEDecodeException, WaveDecoder |
4 | 7 |
|
5 | 8 | import arcade |
6 | 9 |
|
7 | 10 | frame_count = 0 |
8 | 11 | player = None |
9 | 12 |
|
10 | 13 |
|
| 14 | +@pytest.mark.parametrize("load", [arcade.Sound, arcade.load_sound]) |
| 15 | +@pytest.mark.parametrize("streaming", [False, True]) |
| 16 | +@pytest.mark.parametrize("path_kind", ["path", "resource"]) |
| 17 | +def test_sound_explicit_decoder(load, streaming, path_kind, tmp_path, mocker): |
| 18 | + if path_kind == "path": |
| 19 | + # An explicit decoder must work without a registered file extension. |
| 20 | + path = tmp_path / "sound.custom" |
| 21 | + with wave.open(str(path), "wb") as audio: |
| 22 | + audio.setparams((1, 1, 8000, 80, "NONE", "not compressed")) |
| 23 | + audio.writeframes(b"\x80" * 80) |
| 24 | + else: |
| 25 | + path = ":resources:sounds/laser1.wav" |
| 26 | + |
| 27 | + decoder = WaveDecoder() |
| 28 | + decode = mocker.spy(decoder, "decode") |
| 29 | + sound = load(path, streaming, decoder=decoder) |
| 30 | + |
| 31 | + decode.assert_called_once() |
| 32 | + assert decode.call_args.args == (sound.file_name, None) |
| 33 | + assert decode.call_args.kwargs["streaming"] is streaming |
| 34 | + assert Path(sound.file_name).is_file() |
| 35 | + assert sound.source.duration > 0 |
| 36 | + assert sound.source.audio_format.channels > 0 |
| 37 | + assert isinstance(sound.source, StreamingSource if streaming else StaticSource) |
| 38 | + |
| 39 | + source = sound.source.get_queue_source() |
| 40 | + audio_data = source.get_audio_data(1024) |
| 41 | + assert audio_data is not None |
| 42 | + assert audio_data.length > 0 |
| 43 | + if path_kind == "path": |
| 44 | + assert sound.source.duration == pytest.approx(0.01) |
| 45 | + assert sound.source.audio_format.sample_rate == 8000 |
| 46 | + assert audio_data.data == b"\x80" * 80 |
| 47 | + |
| 48 | + |
| 49 | +@pytest.mark.parametrize("load", [arcade.Sound, arcade.load_sound]) |
| 50 | +@pytest.mark.parametrize("streaming", [False, True]) |
| 51 | +def test_sound_explicit_decoder_failure(load, streaming, mocker): |
| 52 | + decoder = WaveDecoder() |
| 53 | + error = WAVEDecodeException("Explicit decoder failed") |
| 54 | + decode = mocker.patch.object(decoder, "decode", side_effect=error) |
| 55 | + |
| 56 | + # This valid WAV would load successfully if automatic decoders were tried. |
| 57 | + expected_error = WAVEDecodeException if load is arcade.Sound else FileNotFoundError |
| 58 | + with pytest.raises(expected_error, match="Explicit decoder failed") as exc: |
| 59 | + load(":resources:sounds/laser1.wav", streaming, decoder=decoder) |
| 60 | + |
| 61 | + decode.assert_called_once() |
| 62 | + if load is arcade.Sound: |
| 63 | + assert exc.value is error |
| 64 | + else: |
| 65 | + assert exc.value.__cause__ is error |
| 66 | + |
| 67 | + |
11 | 68 | def test_sound_normal_load_and_playback(window): |
12 | 69 | global frame_count, player |
13 | 70 |
|
|
0 commit comments