diff --git a/README.md b/README.md index 97ee49f8..6559058c 100644 --- a/README.md +++ b/README.md @@ -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 , a service provided by Falko Oldenburg . * `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. diff --git a/cabal.project b/cabal.project index 90be9908..d5b996c8 100644 --- a/cabal.project +++ b/cabal.project @@ -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 diff --git a/cabal.project.freeze b/cabal.project.freeze index fcf926f9..9805a244 100644 --- a/cabal.project.freeze +++ b/cabal.project.freeze @@ -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, diff --git a/default.nix b/default.nix index 25e02bd4..b745a412 100644 --- a/default.nix +++ b/default.nix @@ -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"; }); @@ -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" ]; @@ -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 + ]; }; @@ -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 ./. [ diff --git a/src/PlaySound.hs b/src/PlaySound.hs index 9644d245..36a92f11 100644 --- a/src/PlaySound.hs +++ b/src/PlaySound.hs @@ -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 () diff --git a/text2speech.yaml b/text2speech.yaml index afa9c42a..2ddc013e 100644 --- a/text2speech.yaml +++ b/text2speech.yaml @@ -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. diff --git a/tttool.cabal b/tttool.cabal index 5041687a..77192492 100644 --- a/tttool.cabal +++ b/tttool.cabal @@ -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