Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Proteaaudio for audio playback #290

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
3 changes: 0 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,6 @@ Other resources in this repository
----------------------------------

* [`oid-decoder.html`](http://htmlpreview.github.io/?https://github.com/entropia/tip-toi-reveng/blob/master/oid-decoder.html) allows you to manually decode an OID image.
* `scripts/update.sh` downloads all gme files from the Ravensburger server (requires perl and the [XML::Simple](http://search.cpan.org/~grantm/XML-Simple/) module).

Instead of downloading all of them, you can conveniently browse them at <http://tiptoi.vakat.de/>, a service provided by Falko Oldenburg <[email protected]>.
* `gameanalyse.c` and `libtiptoi.c` is an alternative tool to investigate gme
files. It can also [replace audio files in gme files](Audio/README.md);
compile and run it for diagnostic output.
Expand Down
7 changes: 7 additions & 0 deletions cabal.project
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,10 @@ source-repository-package
location: https://github.com/nomeata/HPDF
tag: a43e6dd41e8d4e967f1fe9f6e30286a8a9dead64
--sha256: 1s23rnwln40jxr0vnlr0r74sjysrj4s14brvr3nhb7q1y4yb5366

source-repository-package
type: git
location: https://github.com/csabahruska/proteaaudio
tag: 7a22a2e9dcff5b3ce989d353aa4cb1ac4b676d09
subdir: proteaaudio
--sha256: 1n4z69ds5yn0dsnwczpcrhba3c2k1l6v0xnwz6s05kc2kd7a58zi
1 change: 1 addition & 0 deletions cabal.project.freeze
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ constraints: any.HPDF ==1.4.10,
any.pretty ==1.1.3.6,
any.primitive ==0.8.0.0,
any.process ==1.6.16.0,
any.proteaaudio ==1.0.0,
any.random ==1.1,
any.resourcet ==1.3.0,
any.rts ==1.0.2,
Expand Down
34 changes: 26 additions & 8 deletions default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,24 @@ let
sources = import nix/sources.nix;

# Fetch the latest haskell.nix and import its default.nix
haskellNix = import sources.haskellNix {};
haskellNix = import sources.haskellNix {
};

# Peek at https://github.com/input-output-hk/haskell.nix/blob/master/ci.nix
# for supported nixpkgs and ghc versions
# or https://github.com/input-output-hk/haskell.nix/blob/master/docs/reference/supported-ghc-versions.md
nixpkgsSrc = haskellNix.sources.nixpkgs-unstable;
nixpkgsArgs = haskellNix.nixpkgsArgs;
nixpkgsArgs = haskellNix.nixpkgsArgs // {
overlays = haskellNix.nixpkgsArgs.overlays ++ [
(self: super: {
# these help haskell.nix to resolve system library dependencies
dsound = null;
pulse = super.libpulseaudio;
# to work around https://github.com/input-output-hk/haskell.nix/issues/2002
kmod = super.kmod.override { xz = self.xz.override { enableStatic = false;};};
})
];
};

pkgs = import nixpkgsSrc nixpkgsArgs;
pkgs-osx = import nixpkgsSrc (nixpkgsArgs // { system = "x86_64-darwin"; });
Expand Down Expand Up @@ -42,6 +53,9 @@ let
modules = [{
# smaller files
packages.tttool.dontStrip = false;
packages.proteaaudio.components.library.build-tools = pkgs.lib.mkForce [
pkgs.buildPackages.haskellPackages.c2hs
];
}] ++
pkgs.lib.optional pkgs.hostPlatform.isMusl {
packages.tttool.configureFlags = [ "--ghc-option=-static" ];
Expand All @@ -55,7 +69,11 @@ let
(tttool-project pkgs sha256).tttool.components.exes.tttool;
tttool-shell = pkgs: sha256:
(tttool-project pkgs sha256).shellFor {
buildInputs = [ pkgs.ghcid ];
buildInputs = with pkgs; [
ghcid
picotts
vorbis-tools
];
};


Expand Down Expand Up @@ -83,15 +101,15 @@ let

in rec {
shell = tttool-shell pkgs
"12fm0i61zhah9yrkf0lmpybrcl0q91gb3krib12zz6qg5fx0lbw7";
"1x9v6vgycidmjaapxfvc6zn3zwawahh9ly3kx8sp0w42j3h8d50d";
linux-exe = tttool-exe pkgs
"12fm0i61zhah9yrkf0lmpybrcl0q91gb3krib12zz6qg5fx0lbw7";
"1x9v6vgycidmjaapxfvc6zn3zwawahh9ly3kx8sp0w42j3h8d50d";
windows-exe = tttool-exe pkgs.pkgsCross.mingwW64
"1x16mjjx4wnzksmpi4jg6ykvfvdshrhp58gciy9lfslavy9clf3a";
"0b7kka4105rh0fagx25a9plangdpvh1ca7r2kfyiq6kya7hnlgz3";
static-exe = tttool-exe pkgs.pkgsCross.musl64
"12fm0i61zhah9yrkf0lmpybrcl0q91gb3krib12zz6qg5fx0lbw7";
"1x9v6vgycidmjaapxfvc6zn3zwawahh9ly3kx8sp0w42j3h8d50d";
osx-exe = tttool-exe pkgs-osx
"12fm0i61zhah9yrkf0lmpybrcl0q91gb3krib12zz6qg5fx0lbw7";
"1x9v6vgycidmjaapxfvc6zn3zwawahh9ly3kx8sp0w42j3h8d50d";
osx-exe-bundle = osx-bundler pkgs-osx osx-exe;

static-files = sourceByRegex ./. [
Expand Down
62 changes: 19 additions & 43 deletions src/PlaySound.hs
Original file line number Diff line number Diff line change
@@ -1,50 +1,26 @@
module PlaySound (playSound) where

import System.Process
import System.Exit
import Control.Monad
import Control.Exception
import System.IO.Error
import System.IO
import System.Directory
import System.FilePath
import qualified Data.ByteString.Lazy as B
import System.Environment.Executable
import qualified Data.ByteString.Lazy.Char8 as B

import Sound.ProteaAudio

players :: FilePath -> FilePath -> [(FilePath, [String])]
players myDir fn =
[ ("sox", ["-q", fn, "-d"])
, (myDir </> "contrib" </> "playmus", [fn])
]

playSound :: B.ByteString -> IO ()
playSound content = do
dir <- getTemporaryDirectory
(tmp, h) <- openTempFile dir "tttool-audio.tmp"
B.hPutStr h content
hClose h

(myDir,_) <- splitExecutablePath
sampleFromMemory :: B.ByteString -> Float -> IO Sample
sampleFromMemory bs
| B.take 4 bs == B.pack "RIFF" = sampleFromMemoryWav (B.toStrict bs)
| B.take 4 bs == B.pack "OggS" = sampleFromMemoryOgg (B.toStrict bs)
| B.take 3 bs == B.pack "ID3" || B.take 2 bs `elem`
[B.pack "\xFF\xFB", B.pack "\xFF\xF3", B.pack "\xFF\xF2"]
= sampleFromMemoryMp3 (B.toStrict bs)
| otherwise = error "Could not detect audio format"
where magic = B.take 4 bs

tryPrograms (players myDir tmp) $ do
putStrLn "Could not play audio file."
putStrLn "Do you have \"sox\" installed?"

removeFile tmp

tryPrograms [] e = e
tryPrograms ((c,args):es) e = do
-- Missing programs cause exceptions on Windows, but error 127 on Linux.
-- Try to handle both here.
r <- tryJust (guard . isDoesNotExistError) $ do
ph <- runProcess c args Nothing Nothing Nothing Nothing Nothing
ret <- waitForProcess ph
if ret == ExitSuccess then return True
else if ret == ExitFailure 127 then return False
else do
putStrLn $ "Failed to execute \"" ++ c ++ "\" (" ++ show ret ++ ")"
exitFailure
case r of
Right True -> return ()
_ -> tryPrograms es e
playSound :: B.ByteString -> IO ()
playSound content = do
_ok <- initAudio 1 22050 512
soundStopAll
sample <- sampleFromMemory content 1
_sound <- soundPlay sample 1 1 0 1
-- finishAudio
return ()
6 changes: 3 additions & 3 deletions text2speech.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ welcome: hello
language: en
scripts:
8066:
- $mode==1? P(mode_one)
- $mode==2? P(mode_two)
- $mode==3? P(mode_three)
- $mode==0? P(mode_one) $mode := 1
- $mode==1? P(mode_two) $mode := 2
- $mode==2? P(mode_three) $mode := 0

# But instead of manually creating files hello.ogg, mode_one.ogg and
# mode_two.ogg, you can specify text to be spoken for them.
Expand Down
1 change: 1 addition & 0 deletions tttool.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ executable tttool
build-depends: vector >= 0.10 && < 0.13
build-depends: yaml >= 0.8 && < 0.12
build-depends: zlib >= 0.5 && < 0.7
build-depends: proteaaudio ^>= 1.0

hs-source-dirs: src
default-language: GHC2021
Expand Down