Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ sudo: required
dist: trusty
node_js: stable
install:
- npm install -g purescript@0.13.8 pulp@15.0.0 bower
- npm install -g purescript@0.15.4 pulp@16.0.0 bower
script:
- bower install
- npm run -s build
Expand Down
26 changes: 13 additions & 13 deletions bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "purescript-webaudio",
"version": "0.1.0",
"version": "0.1.2",
"description": "A PureScript wrapper for the WebAudio API.",
"repository": {
"type": "git",
Expand All @@ -22,17 +22,17 @@
"tests"
],
"dependencies": {
"purescript-arrays": "^6.0.1",
"purescript-foldable-traversable": "^5.0.1",
"purescript-lists": "^6.0.1",
"purescript-math": "^3.0.0",
"purescript-maybe": "^5.0.0",
"purescript-tuples": "^6.0.1",
"purescript-strings": "^5.0.0",
"purescript-effect": "^3.0.0",
"purescript-aff": "^6.0.0",
"purescript-arraybuffer-types": "^3.0.0",
"purescript-arraybuffer": "^11.0.1",
"purescript-web-events": "^3.0.0"
"purescript-arrays": "^7.1.0",
"purescript-foldable-traversable": "^6.0.0",
"purescript-lists": "^7.0.0",
"purescript-math": "^4.0.0",
"purescript-maybe": "^6.0.0",
"purescript-tuples": "^7.0.0",
"purescript-strings": "^6.0.0",
"purescript-effect": "^4.0.0",
"purescript-aff": "^7.1.0",
"purescript-arraybuffer-types": "^3.0.2",
"purescript-arraybuffer": "^13.0.0",
"purescript-web-events": "^4.0.0"
}
}
5 changes: 5 additions & 0 deletions build-examples.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
echo "*** Building decode ***"
npm run -s spago:build:example:decode
echo "*** Building decodeAsync ***"
npm run -s spago:build:example:decodeAsync
echo "*** Building gain ***"
npm run -s spago:build:example:gain
echo "*** Building square-wave ***"
npm run -s spago:build:example:squareWave
echo "*** Building props ***"
npm run -s spago:build:test:props
6 changes: 6 additions & 0 deletions decodeAsync.dhall
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,17 @@ in conf // {
sources = conf.sources # [ "examples/decodeAsync/**/*.purs" ],
dependencies = conf.dependencies
# [ "affjax"
, "affjax-web"
, "arraybuffer"
, "arrays"
, "either"
, "exceptions"
, "foldable-traversable"
, "http-methods"
, "newtype"
, "parallel"
, "unsafe-coerce"
, "web-dom"
, "web-html"
]
}
44 changes: 22 additions & 22 deletions examples/decode/SimpleDom.js
Original file line number Diff line number Diff line change
@@ -1,54 +1,54 @@
"use strict";

exports.maybeFn = function (nothing, just, a) {
export function maybeFn(nothing, just, a) {
return a == null ? nothing : just(a);
};
}

exports.makeXMLHttpRequest = function () {
export function makeXMLHttpRequest() {
return new XMLHttpRequest();
};
}

exports.unsafeOpen = function (obj, method, url) {
export function unsafeOpen(obj, method, url) {
return function () {
obj.open(method, url);
return {};
};
};
}

exports.unsafeResponseType = function (obj) {
export function unsafeResponseType(obj) {
return function () {
return obj.responseType;
};
};
}

exports.unsafeSetResponseType = function (obj, rt) {
export function unsafeSetResponseType(obj, rt) {
return function () {
obj.responseType = rt;
return {};
};
};
}

exports.unsafeResponse = function (obj) {
export function unsafeResponse(obj) {
return function () {
return obj.response;
};
};
}

exports.unsafeSend = function (obj) {
export function unsafeSend(obj) {
return function () {
obj.send();
return {};
};
};
}

exports.unsafeSendWithPayload = function (obj, payload) {
export function unsafeSendWithPayload(obj, payload) {
return function () {
obj.send(payload);
return {};
};
};
}

exports.unsafeAddEventListener = function (targ) {
export function unsafeAddEventListener(targ) {
return function (cb) {
return function (src) {
return function () {
Expand All @@ -58,18 +58,18 @@ exports.unsafeAddEventListener = function (targ) {
};
};
};
};
}

exports.unsafeEventTarget = function (event) {
export function unsafeEventTarget(event) {
return function () {
return event.target;
};
};
}

exports.unsafeEventProp = function (prop) {
export function unsafeEventProp(prop) {
return function (event) {
return function () {
return event[prop];
};
};
};
}
24 changes: 21 additions & 3 deletions examples/decodeAsync/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module DecodeAsync where

import Prelude

import Affjax (defaultRequest, request)
import Affjax.Web (defaultRequest, request)
import Affjax.ResponseFormat as ResponseFormat
import Audio.WebAudio.AudioBufferSourceNode (StartOptions, setBuffer, startBufferSource)
import Audio.WebAudio.BaseAudioContext (createBufferSource, currentTime, decodeAudioDataAsync, destination, newAudioContext)
Expand All @@ -13,10 +13,18 @@ import Data.ArrayBuffer.ArrayBuffer (empty)
import Data.Either (Either(..))
import Data.HTTP.Method (Method(..))
import Data.Maybe (Maybe(..))
import Data.Newtype (wrap)
import Data.Traversable (traverse)
import Effect (Effect)
import Effect.Aff (Aff, Fiber, launchAff)
import Effect.Class (liftEffect)
import Effect.Exception (throw)
import Unsafe.Coerce (unsafeCoerce)
import Web.DOM.ParentNode (querySelector)
import Web.Event.EventTarget (EventTarget, addEventListener, eventListener)
import Web.HTML (window)
import Web.HTML.HTMLDocument (toParentNode)
import Web.HTML.Window (document)

type ElapsedTime = Number

Expand Down Expand Up @@ -67,8 +75,8 @@ playSoundAt ctx mbuffer elapsedTime =
_ ->
pure unit

main :: Effect (Fiber Unit)
main = launchAff $ do
loadPlayBuffers :: Effect (Fiber Unit)
loadPlayBuffers = launchAff $ do
ctx <- liftEffect newAudioContext
buffers <- loadSoundBuffers ctx ["hihat.wav", "kick.wav", "snare.wav"]
_ <- liftEffect $ playSoundAt ctx (buffers !! 0) 0.0
Expand All @@ -78,3 +86,13 @@ main = launchAff $ do
_ <- liftEffect $ playSoundAt ctx (buffers !! 1) 2.0
_ <- liftEffect $ playSoundAt ctx (buffers !! 2) 2.5
pure unit

main :: Effect Unit
main = do
doc <- map toParentNode (window >>= document)
playButton <- querySelector (wrap "#play") doc
case playButton of
Just e -> do
el <- eventListener \_ -> loadPlayBuffers
addEventListener (wrap "click") el false (unsafeCoerce e :: EventTarget)
Nothing -> throw "no play button"
17 changes: 16 additions & 1 deletion examples/decodeAsync/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,22 @@
<head>
</head>
<body>
<h1>Test04 - Load Audio Buffers asynchronously</h1>
<style>
.button {
color: white;
border-radius: 12px;
padding: 15px 32px;
text-align: center;
font-size: 16px
}
.play-button {
background-color: green;
}
</style>
<div>
<h1>Load Audio Buffers asynchronously</h1>
<button id="play" class="button play-button">PLAY</button>
</div>
<script type="text/javascript" src="output/bundle.js"></script>
</body>
</html>
81 changes: 58 additions & 23 deletions examples/gain/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,74 @@ module Gain where

import Prelude

import Audio.WebAudio.BaseAudioContext (createGain, currentTime, destination, newAudioContext, sampleRate)
import Audio.WebAudio.AudioContext (createMediaElementSource)
import Audio.WebAudio.AudioBufferSourceNode (defaultStartOptions, setBuffer, startBufferSource)
import Audio.WebAudio.BaseAudioContext (createGain, createBufferSource, decodeAudioData, destination, newAudioContext)
import Audio.WebAudio.AudioParam (setValueAtTime)
import Audio.WebAudio.GainNode (gain)
import Audio.WebAudio.Types (connect)
import Audio.WebAudio.Types (AudioBuffer, AudioBufferSourceNode, connect)
import Data.ArrayBuffer.Types (ArrayBuffer)
import Data.Newtype (wrap)
import Effect (Effect)
import Effect.Console (logShow)
import Effect.Console (warn)
import Effect.Exception (throw)
import SimpleDom (DOMEvent, HttpData(..), HttpMethod(..), ProgressEventType(..)
, XMLHttpRequest, addProgressEventListener, makeXMLHttpRequest, open
, response, send, setResponseType)
import Partial.Unsafe (unsafePartial)
import Unsafe.Coerce (unsafeCoerce)
import Web.DOM.ParentNode (querySelector)
import Web.Event.EventTarget (EventTarget, addEventListener, eventListener)
import Web.HTML (window)
import Web.HTML.HTMLDocument (toNonElementParentNode)
import Web.HTML.HTMLDocument (toParentNode)
import Web.HTML.Window (document)
import Web.DOM.NonElementParentNode (getElementById)
import Data.Maybe (Maybe(..))

toArrayBuffer :: forall a. (HttpData a) -> ArrayBuffer
toArrayBuffer hd =
unsafePartial
case hd of
(ArrayBufferData a) -> a

-- | 3 secs after the audio begins playing, set the value (i.e., volume)
-- | of the gain node to 0.3 (i.e., a 70% reduction)

play :: XMLHttpRequest -- |^ the request object
-> DOMEvent -- |^ the load event
-> Effect Unit
play req _ = do
ctx <- newAudioContext
src <- createBufferSource ctx
gainNode <- createGain ctx
dst <- destination ctx
connect src gainNode
connect gainNode dst
gainParam <- gain gainNode
_ <- setValueAtTime 0.3 3.0 gainParam
audioData <- response req
decodeAudioData ctx (toArrayBuffer audioData) (play0 src) warn

play0 :: AudioBufferSourceNode
-> AudioBuffer
-> Effect Unit
play0 src buf = do
setBuffer buf src
startBufferSource defaultStartOptions src

playWavFile :: Effect Unit
playWavFile = do
req <- makeXMLHttpRequest
open GET "gain.wav" req
setResponseType "arraybuffer" req
addProgressEventListener ProgressLoadEvent (play req) req
send NoData req
pure unit

main :: Effect Unit
main = do
doc <- map toNonElementParentNode (window >>= document)
noise <- getElementById "noise" doc
case noise of
Just el -> void do
cx <- newAudioContext
src <- createMediaElementSource cx el
gainNode <- createGain cx
dest <- destination cx
connect src gainNode
connect gainNode dest
gainParam <- gain gainNode
_ <- setValueAtTime 0.3 3.0 gainParam
sr <- sampleRate cx
logShow sr
t <- currentTime cx
logShow t
Nothing -> throw "No 'noise' node!"
doc <- map toParentNode (window >>= document)
playButton <- querySelector (wrap "#play") doc
case playButton of
Just e -> do
el <- eventListener \_ -> playWavFile
addEventListener (wrap "click") el false (unsafeCoerce e :: EventTarget)
Nothing -> throw "no play button"
Loading