packages feed

live-sequencer 0.0.5.2 → 0.0.6

raw patch · 10 files changed

+108/−20 lines, 10 filesdep ~directorydep ~wxdep ~wxcorePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: directory, wx, wxcore

API changes (from Hackage documentation)

Files

README.md view
@@ -81,7 +81,7 @@ in order to allow offline rendering of music that you programmed within the Live-Sequencer. You may generate a standard MIDI file-using functions from the `Render` module.+using functions from the "Render" module. To this end load your song module into GHCi and call  ~~~~@@ -195,6 +195,9 @@  * term size:   With this limit you can prevent memory leaks.+  You may also hit the limit if you write a whole song in a big list.+  Better split the list up into sections+  and define a function for each section.  * term depth:   With this limit you can prevent unbalanced expression trees.@@ -283,3 +286,72 @@ * PAUSE: Toggle between real time and single step mode  * FAST FORWARD: Next element in single step mode++# Tips & Tricks++## Append with overlap++The `(+:+)` operator can only handle precise concatenation of event streams.+However, in common music you also have to handle upbeats and legato.+Technically, this means that there may be events before and after a core part.+First, let us consider the case where there are events after the core part.+We define a `Block` data structure containing two or more parallel `Track`s.+For simplicity we now use only two tracks:++~~~~+type Track = [Event Message] ;+data Block = Block Track Track ;+~~~~++The first track specifies the length of the block. It cannot overlap.+If you have no other use for it, fill it with rests.+The second track can be shorter or longer than the first track.+Everything longer will be merged with subsequent `Block`s.+This is, how we convert a sequence of overlapping blocks+to a plain `Event` stream:++~~~~+consBlock :: Block -> [Event Message] -> [Event Message] ;+consBlock (Block t0 t1) y  =  t0 +:+ y  =:=  t1 ;++concatBlocks :: [Block] -> [Event Message] ;+concatBlocks = foldr consBlock [] ;+~~~~++Blocks with events before a core part+must be handled by delaying every block by the maximum time+that an event can occur before the core.++## Tempo changes++Changing the tempo within a song is a bit tricky,+especially in the presence of overlapping blocks (see above).+You want++* Consistency.+  Events that would occur at the same point in time without tempo changes+  shall occur at the same point in time in the presence of tempo changes, too.+  This rules out fixing the time periods in an event stream+  and change them later, but before merging it with other streams.++* Composability.+  You want to play only parts of the song+  or concatenate multiple parts of a song.+  This rules out external description of tempo progression.++The best I could come up with+is to extend the `Midi.Message` data type by a `SetTempo` constructor.+After you have comletely composed the song+you scan the event stream for these constructors+and change the `Wait` events accordingly.+The LiveSequencer language is untyped,+thus you could simply use a `SetTempo` constructor+as if it were a constructor of `Midi.Message`.+Though, for Haskell compatibility I suggest you wrap `Midi.Message`+in a custom datatype that adds the `SetTempo` constructor.++The MIDI file format and ALSA sequencer even support+a `SetTempo` statement natively.+However, we cannot easily make use of it,+since it is not obvious how to merge streams containing `SetTempo`+in the general case.
data/base/Midi.hs view
@@ -34,10 +34,15 @@     ) where  import Function-import Pitch ( Pitch )+-- import Pitch ( Pitch )+{-+avoid dependency on Pitch+otherwise we get conflicts with custom pitch definitions in ATPS and LAC paper.+-} import Bool ( ifThenElse )  +type Pitch = Integer ; type Time = Integer ; type Velocity = Integer ; type Program = Integer ;
data/example/DeBruijn.hs view
@@ -9,6 +9,14 @@ import Prelude ( Integer, fromInteger, fromIntegral, ($), (.), (+), (-), (<), mod ) ;  +{-+main :: [Event Message] ;+main =+   [Event (On 60 64), Wait 1000, Event (Off 60 64)]+   +++   [Event (On 64 64), Wait 1000, Event (Off 64 64)] ;+-}+ main :: [ Event (Channel Message) ] ; main =    channel 0 $ changeTempo timeUnit $
live-sequencer.cabal view
@@ -1,15 +1,14 @@ Name:          live-sequencer-Version:       0.0.5.2+Version:       0.0.6 Author:        Henning Thielemann and Johannes Waldmann Maintainer:    Henning Thielemann <haskell@henning-thielemann.de>, Johannes Waldmann <waldmann@imn.htwk-leipzig.de> Category:      Sound, Music, GUI License:       GPL License-file:  LICENSE Cabal-Version: >= 1.6-Tested-With:   GHC==6.12.3-Tested-With:   GHC==7.2.1, GHC==7.4.2, GHC==7.6.3+Tested-With:   GHC==7.8.4, GHC==8.0.1 Homepage:      http://www.haskell.org/haskellwiki/Live-Sequencer-Bug-Reports:   http://dfa.imn.htwk-leipzig.de/bugzilla/describecomponents.cgi?product=live-sequencer+Bug-Reports:   https://hub.darcs.net/thielema/livesequencer Synopsis:      Live coding of MIDI music Description:    An editor shows a textual description of music (like Haskore),@@ -67,13 +66,13 @@   http/disable/HTTPServer/Option.hs  Source-Repository head-  Type: git-  Location: git://dfa.imn.htwk-leipzig.de/srv/git/seq/+  Type: darcs+  Location: https://hub.darcs.net/thielema/livesequencer  Source-Repository this-  Type: git-  Tag: 0.0.5.2-  Location: https://github.com/thielema/livesequencer+  Tag: 0.0.6+  Type: darcs+  Location: https://hub.darcs.net/thielema/livesequencer  Flag gui   Description: Build the wxWidgets GUI for the sequencer@@ -169,15 +168,15 @@     containers >=0.3 && <0.6,     bytestring >=0.9 && <0.11,     process >=1.0 && <1.5,-    directory >=1.0 && <1.3,+    directory >=1.0 && <1.4,     filepath >=1.1 && <1.5,     base >=4.2 && <5  Executable live-sequencer-gui   If flag(gui)     Build-Depends:-      wx >=0.12.1 && <0.14,-      wxcore >=0.12.1 && <0.14,+      wx >=0.12.1 && <0.93,+      wxcore >=0.13.2 && <0.93,       stm >=2.2 && <2.5,       concurrent-split >=0.0 && <0.1,       transformers >=0.2.2 && <0.6,@@ -196,7 +195,7 @@       containers >=0.3 && <0.6,       bytestring >=0.9 && <0.11,       process >=1.0 && <1.5,-      directory >=1.0 && <1.3,+      directory >=1.0 && <1.4,       filepath >=1.1 && <1.5,       base >=4.2 && <5   Else@@ -256,7 +255,7 @@       alsa-seq >=0.6 && <0.7,       alsa-core >=0.5 && <0.6,       unix >=2.4 && <2.8,-      directory >=1.0 && <1.3,+      directory >=1.0 && <1.4,       transformers >=0.2.2 && <0.6,       base >=4.2 && <5   Else
src/Event.hs view
@@ -362,6 +362,7 @@     t <- fmap (mappend (ALSA.latencyNano sq)) $ AccM.get stateTime     ALSA.sendAllNotesOffLater t     ALSA.forwardStoppedQueue t+--    AccM.set Event.stateTime t   prepare ::
src/Option.hs view
@@ -39,7 +39,7 @@  -- the formatted value might look ugly defltLatencyStr :: String-defltLatencyStr = "0.05"+defltLatencyStr = "0.2"  getDeflt :: IO Option getDeflt = do
src/Term.hs view
@@ -19,6 +19,7 @@ import Control.Monad ( liftM2, mzero ) import Control.Functor.HT ( void ) import Data.Char (isUpper, isLower)+-- import Data.Eq.HT (equating) import Data.Ord (comparing)  @@ -29,9 +30,10 @@      Identifier { range :: Range, name :: String }  instance Eq Identifier where--- | FIXME: this is ignoring the module.+-- FIXME: this is ignoring the module. -- for a complete implementation, we'd need fully qualified names     i == j = name i == name j+--    (==) = equating name  instance Ord Identifier where     compare = comparing name
src/Time.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE EmptyDataDecls #-}+{- | Similar to "Data.Fixed" -} module Time where  import Control.Concurrent ( threadDelay )
src/Type.hs view
@@ -34,7 +34,7 @@       }  -operators :: [[([Char], Assoc)]]+operators :: [[(String, Assoc)]] operators =   [ [ ( "->", AssocRight ) ] --  , [ ( ",", AssocRight) ]
src/Utility/WX.hs view
@@ -37,4 +37,4 @@         (\nb -> void . WXCMZ.notebookSetSelection nb)  splitterWindowSetSashGravity :: WX.SplitterWindow a -> Double -> IO ()-splitterWindowSetSashGravity _w _g = return ()+splitterWindowSetSashGravity = WXCMZ.splitterWindowSetSashGravity