Coder Social home page Coder Social logo

csabahruska / proteaaudio Goto Github PK

View Code? Open in Web Editor NEW
28.0 6.0 8.0 5.5 MB

Simple audio library for Windows, Linux, OSX. Supports Mp3, Ogg, Wav playback and multichannel mixing.

Haskell 1.19% C++ 50.18% C 48.62%
haskell audio ogg-vorbis wav osx windows linux mixer mp3

proteaaudio's Introduction

Overview

ProteaAudio is a minimalist stereo audio mixer/playback library for

  • Linux
  • MacOS
  • Windows

Supported audio formats:

  • Wav
  • Ogg
  • Mp3
  • Raw linear PCM

Audio backend flavours

The proteaaudio library has two low-level backend implementation.

Both library implements the same Haskell API.

proteaaudio's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

proteaaudio's Issues

No Audio devices found

Hello!

When using the normal proteaaudio, I cannot play any audio because no devices are found:

DeviceAudioRt ERROR: No audio devices found!

I have tested both with proteaaudio-0.9.4 from Hackage as well as with proteaaudio-1.0.0.
I am running it on Linux with pipewire 1:0.3.77-2.

I ended up using proteaaudio-sdl which works, so there is no time pressure to fix this quickly. I just wanted to inform you that there might be a problem when using pipewire which I assume to be the cause.

Library Design

I have recently started using this library and I like how simple it is, and I think it is great that it works across all major operating systems.

However, I think the library design has some shortcomings.

  1. Some functions that can fail will not indicate this at all and just fail silently. For example, loading a sample using sampleFromFileSource on a file which does not exist will not fail, but just result in no sound being played. This makes it very difficult to find issues. Calling initAudio twice should maybe also cause an error, but it does not.
  2. Many of the functions that can fail will just return IO Bool. If they return False, it is impossible to know what went wrong.
  3. The library does not protect the user from executing commands in the wrong order. I was really surprised to find out that the function loaderAvailable could not be called before initAudio. Additionally, it only returns IO Bool (see point 2) so there is no indication that lack of initAudio was the problem. If initAudio were to return something like an opaque AudioContext that is needed to use loaderAvailable, then the user could not use loaderAvailable before initializing the audio system.
  4. Maybe as an even stronger version of point 3, it might be good to provide a bracket-like version of handling the audio system. Something like withAudio :: (AudioContext -> IO a) -> IO a that initializes the audio system, runs the given function, and then cleans up the audio system. This would make it impossible to forget to clean up the audio system. Similar logic would maybe apply to Sample.
  5. It is difficult to get information back out of the system.
    • The types Sample and Sound are opaque and do not have Eq or Ord instances.
    • There is no way to find out which Sample corresponds to a given Sound.
    • There is no way to find out which channel a given Sound is playing on.
    • There is no way to find out which Sample or Sound is playing on a given channel.
    • There is no way to find out if a given channel is currently playing.
    • There is no way to find out if a given channel is currently playing or looping.
    • There is no way to find out what volume a given channel is playing at.

I know this is a lot of criticism, but I am really not trying to be rude. Instead, I want to make suggestions because I think this library is important and I want to help make it better.

It is also very possible that there are good reasons for why things are the way they are or that I am mistaken, so please let me know what you think.

Get current position of audio engine

Hello, I'm looking to use this library for a simple terminal based rhythm game. Not looking for too much functionality, so this library seems great. However, one thing that would be very helpful is a way to query the current position of the audio engine as it plays a specific sound, potentially based off of the current number of samples played, something similar to Unity's AudioSettings.dspTime. This would allow the game to be synced to a more accurate audio position.

[REQ] add a (GH-compliant) license file

Hi there, 1st of all thanks for this awesome work !

Since we've 'doxed' it in our HyMPS project (under AUDIO section \ Libraries page \ Handling), can you please add a GH-compliant license file for it ?

As you know, expliciting licensing terms is extremely important to let anyone better/faster understand how to reuse/adapt/modify sources (and not only) in other open projects and vice-versa.

Although it may sounds like a minor aspect, license file omission obviously causes an inconsistent generation of the relative badge too:


(badge-generator URL: https://badgen.net/github/license/csabahruska/proteaaudio)

You can easily set a standardized one through the GH's license wizard tool.

Last but not least, let us know how we could improve - in your opinion - our categorizations and links to resources in order to favor collaboration between developers (and therefore evolution) of listed projects.

Hope that helps/inspires !

Using native audio backend without SDL backend installed causes noticable delay

I created a quick test app using brick that simply toggles the playing state of an audio file whenever you push a key. https://github.com/huantianad/proteaaudio-test

When I run this app either

  • importing the SDL backend (import Sound.ProteaAudio.SDL)
  • importing the native backend (import Sound.ProteaAudio) while proteaaudio-sdl is included in my cabal build-depends
    the music play/pauses basically immediately when I push a key.

However, if I import the native backed, and don't include proteaaudio-sdl in my build-depends, there's a small delay between pushing a key and the music pausing.

Is this because the native backend has some sort of delay, and including proteaaudio-sdl in my build-depends is somehow causing my program to use the SDL backend instead?

Linux kernel 6.6.1, Pipewire 0.3.84.

Fail to build on M1 Mac

Running cabal install proteaaudio on M1 Mac gives the following error:

Resolving dependencies...
Build profile: -w ghc-9.4.2 -O1
In order, the following will be built (use -v for more details):
 - proteaaudio-0.9.4 (lib) (requires build)
Starting     proteaaudio-0.9.4 (lib)
Building     proteaaudio-0.9.4 (lib)

Failed to build proteaaudio-0.9.4.
Build log (
/Users/kristiansordal/.cabal/logs/ghc-9.4.2/prtd-0.9.4-c9cfa97b.log ):
Configuring library for proteaaudio-0.9.4..
Preprocessing library for proteaaudio-0.9.4..
Building library for proteaaudio-0.9.4..
[1 of 1] Compiling Sound.ProteaAudio ( dist/build/Sound/ProteaAudio.hs, dist/build/Sound/ProteaAudio.o, dist/build/Sound/ProteaAudio.dyn_o )
g++: error: unrecognized command-line option '--target=arm64-apple-darwin'
`g++' failed in phase `C++ Compiler'. (Exit code: 1)
Error: cabal: Failed to build proteaaudio-0.9.4. See the build log above for
details.

Unsure how to go about fixing this, any help is appreciated.

Stereo audio files playing in mono

Audio files loaded from .mp3 and .ogg files are playing in mono, despite being stereo audio files. Happens both using native and SDL backends, on Linux kernel 6.6.1, Pipewire 0.3.84.

Not sure if I'm doing something wrong when init-ing the audio system, or my files are bad.

Unable to build with GHC 8.10

Currently, it is impossible to pass flags to the C++ compiler, since GHC 8.10 will use only -optcxx for that, whereas before, -optc would suffice.
Cabal however does currently not evaluate the cxx-sources and cxx-options fields correctly. This means, the necessary flags will never pass from cabal-install > ghc > gcc / clang / ...

This issue is blocked by: haskell/cabal#6421

DeviceAudioRt::soundStop stops slot, not handle (?)

The function looks like this, and what it seems to do, is treating the sound handle as an index to the playable/playing slots:

bool DeviceAudioRt::soundStop(unsigned int sound) {
    if(!sound||(sound>m_nSound)||!ma_sound[sound-1].isPlaying) return false;
    ma_sound[sound-1].isPlaying=false;
    return true;
}

The sound, however, might be mapped to any slot (the first one found free in soundPlay, e.g.).
Shouldn't the function do something like this instead (snippet taken from DeviceAudioRt::sampleDestroy) ?

map<unsigned int,AudioSample*>::iterator iter=mm_sample.find(sample);
[...]
for (unsigned int i=0; i<m_nSound; ++i )
    if(ma_sound[i].sample == iter->second)
         ma_sound[i].isPlaying=false;

ExitFailure (-11)

I'm using the following program:

import Control.Concurrent
import Sound.ProteaAudio
import Data.ByteString
main :: IO ()
main = do
  let samples = pack $ [round $ (100 *) $ sin $ 2*pi*440*(t/44100)|t<-[1..44100*10]] :: ByteString
  result <- initAudio 2 44100 1024
  print result
  sample <- sampleFromMemoryPcm samples 1 44100 8 1
  soundPlay sample 2 1 0 1
  threadDelay 10000000
  finishAudio

And I'm getting:

Received ExitFailure (-11) when running
Raw command: (/path/to/executable)

I'm using pulseaudio on Nixos, which works fine otherwise.

MP3 support

I’m considering using proteaaudio in one of my projects where I currently shell out to sox. One feature I’ll probably miss is support for MP3 in addition to WAV and OGG. Is that by any chance on your road map and I can just wait for that, or would I have to work around it anyways?

Cannot install proteaaudio on Manjaro

I tried to install proteaaudio for my project using stack, and get this error:

proteaaudio> /tmp/stack-d29b2c9ed80f4aae/proteaaudio-0.9.0/cbits/proAudioRt.cpp:9:2: error:
proteaaudio>      error: #error "No suitable audio backend has found for RtAudio! Install the dev package with headers for the system's audio library and make sure it is in the include path!"
proteaaudio>         9 | #error "No suitable audio backend has found for RtAudio! Install the dev package with headers for the system's audio library and make sure it is in the include path!"
proteaaudio>           |  ^~~~~
proteaaudio>   |
proteaaudio> 9 | #error "No suitable audio backend has found for RtAudio! Install the dev package with headers for the system's audio library and make sure it is in the include path!"
proteaaudio>   |  ^
proteaaudio> `gcc' failed in phase `C Compiler'. (Exit code: 1)

I thought this was due to the fact that I didn't have libpulse-dev. However, it is not available for arch so I tried the most similar packages: libpulse and pulseaudio. Neither of those seemed to fix the compiling error, so I might be on the wrong track.

A way to check if a sound is still active.

I notice that there is a function that gives the number of active sounds. I suggest adding a function of type Sound -> IO Bool that tells you if a given sound is still active. Or a function that tells you what the remaining duration is would work too!

RtApiPulse::callbackEvent: audio write error, Invalid argument.

I am experimenting with proteaaudio-0.9.4, but when I do with this code:


import Sound.ProteaAudio

playSound :: B.ByteString -> IO ()
playSound content = do
    ok <- initAudio 1 22050 0
    print ok
    sample <- sampleFromMemoryWav (B.toStrict content) 1
    sound <- soundPlay sample  1 1 0 1
    -- finishAudio
    return ()

I get log spam saying

RtApiPulse::callbackEvent: audio write error, Invalid argument.

Am I approaching this the wrong way?

Possibility to pause playing sounds

I may be mistaken, but it seems to me like there is no possibility to pause sounds that are currently playing. The only option you have is to stop it altogether, but I'd like to be able to resume it later. My use case is pausing playing sounds in my game when the game is paused.
Would be great if this could be added! Pretty much the only thing I feel like this library is missing.

initAudio just segfaults

Hi, using the initAudio call simply segfaults for me

Prelude> import Sound.ProteaAudio              
Prelude Sound.ProteaAudio>  initAudio 64 44100 1024
/tmp/nix-shell-22659-0/rc: line 1: 23749 Segmentation fault      '/nix/store/g8mbp29sl24xp0ap8l7zbq9ih1ydqiil-stack-1.9.3/bin/stack' $STACK_IN_NIX_EXTRA_ARGS '--internal-re-exec-version=1.9.3' 'ghci'

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.