packages feed

proteaaudio 0.6.5 → 0.7.0

raw patch · 9 files changed

+201/−42 lines, 9 filesdep ~filepathsetup-changedPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: filepath

API changes (from Hackage documentation)

- Sound.ProteaAudio: sampleFromMemoryOgg :: (Ptr CChar) -> (Int) -> (Float) -> IO ((Sample))
+ Sound.ProteaAudio: sampleFromMemoryOgg :: ByteString -> Float -> IO Sample
- Sound.ProteaAudio: sampleFromMemoryWav :: (Ptr CChar) -> (Int) -> (Float) -> IO ((Sample))
+ Sound.ProteaAudio: sampleFromMemoryWav :: ByteString -> Float -> IO Sample

Files

+ CHANGELOG.md view
@@ -0,0 +1,4 @@+# 0.7.0+- use ByteString for in-memory sample loading+- fix: c++ mixer init caused segfaults sometimes+- use PulseAudio backend on Linux
+ README.md view
@@ -0,0 +1,51 @@+# Overview++ProteaAudio is a stereo audio mixer/playback library+for Linux (native ALSA, Jack, and OSS),+Macintosh OS X (CoreAudio and Jack),+and Windows (DirectSound and ASIO) operating systems.+++# Example++```haskell+import Control.Monad+import System.Environment+import System.FilePath+import qualified Data.ByteString as SB+import Control.Concurrent++import Sound.ProteaAudio++waitPayback = do+  n <- soundActive+  when  (n > 0) $ do+    threadDelay 1000000+    waitPayback++main = do+    args <- getArgs+    filename <- case args of+      a : _ -> pure a+      _ -> fail "usage: proteaaudio-play SAMPLE_FILE_NAME"++    result <- initAudio 64 44100 1024 -- max channels, mixing frequency, mixing buffer size+    unless result $ fail "failed to initialize the audio system"++    -- (A) load sample from file+    sampleA <- sampleFromFile filename 1.0 -- volume++    soundPlay sampleA 1 1 0 1 -- left volume, right volume, time difference between left and right, pitch factor for playback+    waitPayback++    -- (B) load from memory buffer+    buffer <- SB.readFile filename+    sampleB <- case takeExtension filename of+      ".ogg" -> sampleFromMemoryOgg buffer 1.0+      ".wav" -> sampleFromMemoryWav buffer 1.0++    soundPlay sampleB 1 1 0 1 -- left volume, right volume, time difference between left and right, pitch factor for playback+    waitPayback++    finishAudio+```
− Setup.hs
@@ -1,2 +0,0 @@-import Distribution.Simple-main = defaultMain
Sound/ProteaAudio.chs view
@@ -1,3 +1,9 @@+{-|+    ProteaAudio is a stereo audio mixer/playback library+    for Linux (native ALSA, Jack, and OSS),+    Macintosh OS X (CoreAudio and Jack),+    and Windows (DirectSound and ASIO) operating systems.+-} {-#LANGUAGE ForeignFunctionInterface#-} #include "proteaaudio_binding.h" module Sound.ProteaAudio (@@ -19,24 +25,108 @@  import Foreign import Foreign.C+import Data.ByteString (ByteString, useAsCStringLen) +-- | audio sample handle newtype Sample = Sample {#type sample_t#}  toSample s = Sample s fromSample (Sample s) = s -{#fun initAudio {`Int', `Int', `Int'} -> `Bool'#}+-- | initializes the audio system+{#fun initAudio+    { `Int' -- ^ the maximum number of sounds that are played parallely. Computation time is linearly correlated to this factor.+    , `Int' -- ^ sample frequency of the playback in Hz. 22050 corresponds to FM radio 44100 is CD quality. Computation time is linearly correlated to this factor.+    , `Int' -- ^ the number of bytes that are sent to the sound card at once. Low numbers lead to smaller latencies but need more computation time (thread switches). If a too small number is chosen, the sounds might not be played continuously. The default value 512 guarantees a good latency below 40 ms at 22050 Hz sample frequency.+    } -> `Bool' -- ^ returns True on success+#}++-- | releases the audio device and cleans up resources {#fun finishAudio {} -> `()'#}-{#fun loaderAvailable {`String'} -> `Bool'#}-{#fun sampleFromMemoryWav {id `Ptr CChar', `Int', `Float'} -> `Sample' toSample#}-{#fun sampleFromMemoryOgg {id `Ptr CChar', `Int', `Float'} -> `Sample' toSample#}-{#fun sampleFromFile {`String', `Float'} -> `Sample' toSample#} -{#fun volume {`Float', `Float'} -> `()'#}+-- | checks if loader for this file type is available+{#fun loaderAvailable+  { `String' -- ^ file extension (e.g. ogg)+  } -> `Bool'+#}++-- | loads wav sound sample from memory buffer+{#fun _sampleFromMemoryWav+  { id `Ptr CChar' -- ^ memory buffer pointer+  , `Int' -- ^ memory buffer size in bytes+  , `Float' -- ^ volume+  } -> `Sample' toSample -- ^ returns handle+#}++-- | loads ogg sound sample from memory buffer+{#fun _sampleFromMemoryOgg+  { id `Ptr CChar' -- ^ memory buffer pointer+  , `Int' -- ^ memory buffer size in bytes+  , `Float' -- ^ volume+  } -> `Sample' toSample -- ^ returns handle+#}++-- | loads wav sound sample from memory buffer+sampleFromMemoryWav :: ByteString -- ^ wav sample data+                    -> Float -- ^ volume+                    -> IO Sample -- ^ return sample handle+sampleFromMemoryWav wavData volume = useAsCStringLen wavData $ \(ptr, size) -> _sampleFromMemoryWav ptr size volume++-- | loads ogg sound sample from memory buffer+sampleFromMemoryOgg :: ByteString -- ^ ogg sample data+                    -> Float -- ^ volume+                    -> IO Sample -- ^ return sample handle+sampleFromMemoryOgg oggData volume = useAsCStringLen oggData $ \(ptr, size) -> _sampleFromMemoryOgg ptr size volume++-- | loads a sound sample from file+{#fun sampleFromFile+  { `String' -- ^ sample filepath+  , `Float' -- ^ volume+  } -> `Sample' toSample -- ^ returns handle+#}++-- | set mixer volume+{#fun volume+  { `Float' -- ^ left+  , `Float' -- ^ right+  } -> `()'+#}++-- | number of currently active sounds {#fun soundActive {} -> `Int'#}++-- | stops all sounds immediately {#fun soundStopAll {} -> `()'#} -{#fun soundLoop {fromSample `Sample', `Float', `Float', `Float', `Float'} -> `()'#}-{#fun soundPlay {fromSample `Sample', `Float', `Float', `Float', `Float'} -> `()'#}-{#fun soundUpdate {fromSample `Sample', `Float', `Float', `Float', `Float'} -> `Bool'#}+-- | plays a specified sound sample continuously and sets its parameters+{#fun soundLoop+  { fromSample `Sample' -- ^ handle of a previously loaded sample+  , `Float' -- ^ left volume+  , `Float' -- ^ right volume+  , `Float' -- ^ time difference between left and right channel in seconds. Use negative values to specify a delay for the left channel, positive for the right+  , `Float' -- ^ pitch factor for playback. 0.5 corresponds to one octave below, 2.0 to one above the original sample+  } -> `()'+#}++-- | plays a specified sound sample once and sets its parameters+{#fun soundPlay+  { fromSample `Sample' -- ^ handle of a previously loaded sample+  , `Float' -- ^ left volume+  , `Float' -- ^ right volume+  , `Float' -- ^ time difference between left and right channel in seconds. Use negative values to specify a delay for the left channel, positive for the right+  , `Float' -- ^ pitch factor for playback. 0.5 corresponds to one octave below, 2.0 to one above the original sample+  } -> `()'+#}++-- | updates parameters of a specified sound+{#fun soundUpdate+  { fromSample `Sample' -- ^ handle of a currently active sound+  , `Float' -- ^ left volume+  , `Float' -- ^ right volume+  , `Float' -- ^ time difference between left and right channel in seconds. Use negative values to specify a delay for the left channel, positive for the right+  , `Float' -- ^ pitch factor for playback. 0.5 corresponds to one octave below, 2.0 to one above the original sample+  } -> `Bool' -- ^ return True in case the parameters have been updated successfully+#}++-- | stops a specified sound immediately {#fun soundStop {fromSample `Sample'} -> `Bool'#}
cbits/proAudioRt.cpp view
@@ -49,6 +49,12 @@ 	oParams.nChannels = 2; // stereo 	oParams.firstChannel = 0; +    // initialize tracks:+    m_nSound=nTracks;+    ma_sound=new _AudioTrack[m_nSound];+	memset(ma_sound,0,m_nSound*sizeof(_AudioTrack));+	m_freqOut = frequency;+ 	try { 		m_dac.openStream( &oParams, NULL, RTAUDIO_SINT16, frequency, &chunkSize, &cbMix, (void *)this ); 		m_dac.startStream();@@ -59,11 +65,6 @@ 		return; 	} -    // initialize tracks:-    m_nSound=nTracks;-    ma_sound=new _AudioTrack[m_nSound];-	memset(ma_sound,0,m_nSound*sizeof(_AudioTrack));-	m_freqOut = frequency; }  DeviceAudioRt::~DeviceAudioRt() {
cbits/proteaaudio_binding.cpp view
@@ -82,7 +82,7 @@     return (int)audio.sampleFromFile(filename, volume); } -sample_t sampleFromMemoryWav(char *data, int size, float volume) {+sample_t _sampleFromMemoryWav(char *data, int size, float volume) {     DeviceAudio & audio = DeviceAudio::singleton();     if((&audio) == 0) return 0;     AudioSample* pSample = loadWavFromMemory((unsigned char*)data, size);@@ -92,7 +92,7 @@     return (int)ret; } -sample_t sampleFromMemoryOgg(char *data, int size, float volume) {+sample_t _sampleFromMemoryOgg(char *data, int size, float volume) {     DeviceAudio & audio = DeviceAudio::singleton();     if((&audio) == 0) return 0;     AudioSample* pSample = loadOggFromMemory((unsigned char*)data, size);
cbits/proteaaudio_binding.h view
@@ -8,8 +8,8 @@ void finishAudio(); int loaderAvailable(char* suffix); void volume(float left, float right);-sample_t sampleFromMemoryWav(char *data, int size, float volume);-sample_t sampleFromMemoryOgg(char *data, int size, float volume);+sample_t _sampleFromMemoryWav(char *data, int size, float volume);+sample_t _sampleFromMemoryOgg(char *data, int size, float volume); sample_t sampleFromFile(char* filename, float volume); int soundActive(); void soundStopAll();
example/play.hs view
@@ -6,22 +6,34 @@  import Sound.ProteaAudio +waitPayback = do+  n <- soundActive+  when  (n > 0) $ do+    threadDelay 1000000+    waitPayback+ main = do     args <- getArgs-    initAudio 64 44100 1024-    let fname = head args-    -- load from file-    smp <- sampleFromFile fname 1.0 -- volume+    filename <- case args of+      a : _ -> pure a+      _ -> fail "usage: proteaaudio-play SAMPLE_FILE_NAME" -    buf <- SB.readFile fname-    -- load from memory buffer-    smp' <- case takeExtension fname of-      ".ogg" -> SB.useAsCStringLen buf $ \(p,i) -> sampleFromMemoryOgg p i 1-      ".wav" -> SB.useAsCStringLen buf $ \(p,i) -> sampleFromMemoryWav p i 1+    result <- initAudio 64 44100 1024 -- max channels, mixing frequency, mixing buffer size+    unless result $ fail "failed to initialize the audio system" -    soundPlay smp' 1 1 0 1-    let loop = do-            n <- soundActive-            when  (n > 0) $ threadDelay 1000000 >> loop-    loop+    -- (A) load sample from file+    sampleA <- sampleFromFile filename 1.0 -- volume++    soundPlay sampleA 1 1 0 1 -- left volume, right volume, time difference between left and right, pitch factor for playback+    waitPayback++    -- (B) load from memory buffer+    buffer <- SB.readFile filename+    sampleB <- case takeExtension filename of+      ".ogg" -> sampleFromMemoryOgg buffer 1.0+      ".wav" -> sampleFromMemoryWav buffer 1.0++    soundPlay sampleB 1 1 0 1 -- left volume, right volume, time difference between left and right, pitch factor for playback+    waitPayback+     finishAudio
proteaaudio.cabal view
@@ -1,5 +1,5 @@ Name:                proteaaudio-Version:             0.6.5+Version:             0.7.0 Synopsis:            Simple audio library for Windows, Linux, OSX. Description:         Simple audio library for Windows, Linux, OSX. Supports Ogg and Wav playback and multichannel mixing. License:             BSD3@@ -8,7 +8,7 @@ Maintainer:          csaba.hruska@gmail.com Stability:           Experimental Category:            Sound-Tested-With:         GHC == 7.10.3+Tested-With:         GHC == 8.0.2 Cabal-Version:       >= 1.10 Build-Type:          Simple @@ -42,6 +42,9 @@    example/play.hs +  README.md+  CHANGELOG.md+ Flag example   Description: Build with example   Default: False@@ -51,7 +54,9 @@   location: https://github.com/csabahruska/proteaaudio  Library-  Build-Depends:        base >= 4 && < 5+  Build-Depends:        base >= 4 && < 5,+                        bytestring == 0.10.*+   default-language:     Haskell2010    Build-tools:          c2hs@@ -70,15 +75,13 @@     CC-Options:         "-D__WINDOWS_DS__"     Extra-Libraries:    stdc++ ole32 dsound winmm   if os(linux)-    CC-Options:         "-D__LINUX_ALSA__ -D__LINUX_PULSE__ -D__LINUX_OSS__"-    Extra-Libraries:    stdc++ pthread asound+    CC-Options:         "-D__LINUX_PULSE__"+    Extra-Libraries:    stdc++ pthread pulse-simple pulse   if os(darwin)     CC-Options:         "-D__MACOSX_CORE__"     Extra-Libraries:    stdc++ pthread     Frameworks:         CoreFoundation CoreAudio -  ghc-options: -O2- executable proteaaudio-play   if flag(example)     Buildable: True@@ -91,6 +94,6 @@    build-depends:     base >= 4 && < 5,-    filepath >=1.4 && <1.5,+    filepath >=1.4 && <2,     bytestring == 0.10.*,     proteaaudio