GithubHelp home page GithubHelp logo

Comments (3)

HexDecimal avatar HexDecimal commented on July 28, 2024 1

You're correct, you do want to be careful what you do in the audio callback. I did it this way to keep artifacts out of the waveform. Better math could be used to make a looping pattern instead.

I still need to look into push vs pull. I leaned towards push because Python doesn't like it as much when it gets called into from C, but that seems to work a little better since I starting passing exceptions to the unraisable hook. The mixer I experimented with can probably be modified to work with the pull method. Keep in mind that with either method you'll have to worry about the Python GIL and that most large Numpy operations will release the GIL for their duration. Any pure-Python implementation of audio handling is going to fall behind in performance, so try to do as much with Numpy as possible.

I already made new a release on PyPI, then I made another release with more bugfixes. If you got it from pip before, then you can upgrade your installation with: pip install -U tcod.

from python-tcod.

HexDecimal avatar HexDecimal commented on July 28, 2024

I've fixed the TypeError, this is my version of your example which will run on the next release of tcod:

import math
import time
from typing import Any

import numpy as np
from numpy.typing import NDArray
from scipy import signal  # type: ignore[import]

import tcod.sdl.audio

VOLUME = 0.04


class PullWave:
    def __init__(self) -> None:
        self.time = 0.0

    def __call__(self, device: tcod.sdl.audio.AudioDevice, stream: NDArray[Any]) -> None:
        sample_rate = device.frequency
        n_samples = device.buffer_samples
        duration = n_samples / sample_rate
        print(f"{duration=} {self.time=}")

        t = np.linspace(self.time, self.time + duration, n_samples, endpoint=False)
        self.time += duration
        wave = signal.square(t * (math.tau * 440)).astype(np.float32)
        wave *= VOLUME

        stream[:] = device.convert(wave)


with tcod.sdl.audio.open(callback=PullWave()) as device:
    print(device)
    time.sleep(1)

I smoothed the waveform and reduced the volume. Sorry for the lack of documentation around this, you seemed to have done pretty well in spite of that.

I'm also interested in what you were having trouble with before you switched to callbacks.

from python-tcod.

splatpope avatar splatpope commented on July 28, 2024
  • Generating the samples during the callback doesn't seem like best practices; I've seen in SDL-related discussion that it should only be used to copy data, but I suppose that doesn't matter if the generation and copy is actually done before the next callback invocation
  • BUT your approach has the obvious advantage of keeping track of time and making sure the waveform is continuous over successive callbacks. I don't think I'll need that but it's quite a neat trick. It would be nice to provide more examples like this in the official docs.
  • The reason I switched to the pull method is because the push method requires synchronizing the buffer's filling with whatever you're playing (playing a buffer that is not full produces noisy artifacts especially when repeatedly playing a very small sample), which gave me multiple headaches. Other SDL-related discussions conclude that the pull method is much more advantageous, especially when mixing UI and DSP logic, which shouldn't be done at all when using the push method (iirc, because timing issues will arise and be a hell to manage)

Finally, are you meaning to say that the error is already fixed, and will not be present in the next version of tcod ?
EDIT : I've looked at the current state of tcod/sdl/audio.py and it seems to be the case

In this case, can you tell me when it will release and be available on pypi? Alternatively, how could I be able to install the current codebase ? (I suppose the easiest way would be to clone, build, install local package with pip)

from python-tcod.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.