Transposing in modes??

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Transposing in modes??

mrzonules
I was wondering if there is the capacity to transpose to a different
mode, or a way to shift a passage of notes diatonicly (or
chromatically). Basically (in version 2.6.5) if I have a set of notes,
"riff = { c8 e g b a g f e }", and want to create a sequence out of
that riff, so that I get something like "sequence = { c8 e g b a g f e
|  d8 f a c b a g f  |  e8 g b d c b a g | ... }", it would be nice to
"sequence ={ \riff
\transpose c d \dorian \riff
\transpose c e \phrygian \riff
\transpose c f \lydian \riff
...
}" to obtain the same results. There are possibly more uses for this,
such as "minor-ifying" pieces, but this would really shine in creating
sequences (for repeditive stuff that shifts around, and especially in
creating practice sheets with scale variations). I suppose you would
encounter problems with accidentals and octave placement, but I'm sure
there are creative ways around this. I think this would be a cool
feature, and have seen questions like this (but were very old, like
version 1.4.x), but did not pertain to lilypond as it stands today. I
am a musician and can code a bit , and would love some help in
undertaking something like this. Hopefully this can benefit the
lilypond and its community as a whole.

-Nathan


_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel
Reply | Threaded
Open this post in threaded view
|

Re: Transposing in modes??

Johannes Schindelin
Hi,

I always wanted to learn how to transform music with scheme, so I
implemented half of it. If some of you experts could look at it and tell
me what could be done more elegantly (Scheme is not my native language),
and especially what needs to be done to make this easy to use, that would
be super!

Ciao,
Dscho


_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel

musical-mode.ly (3K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Transposing in modes??

Han-Wen Nienhuys
Johannes Schindelin wrote:

> Hi,
>
> I always wanted to learn how to transform music with scheme, so I
> implemented half of it. If some of you experts could look at it and tell
> me what could be done more elegantly (Scheme is not my native language),
> and especially what needs to be done to make this easy to use, that would
> be super!
>
> Ciao,
> Dscho
>
>
>
> ------------------------------------------------------------------------
>
> #(define (scale-semitones scale)
> "Get a vector of semitones for a given scale"
> (if (equal? scale "ionian") #(0 2 4 5 7 9 11)
> (if (equal? scale "dorian") #(0 2 3 5 7 9 10)

try (cond .. )

> #(define (alter-mode-aux music transpose-vector)
> "Transpose according to transpose-vector"
> (if (ly:music? music)
> (let ((pitch (ly:music-property music 'pitch)))
>  (if (ly:pitch? pitch)
>   (let* ((off (modulo (ly:pitch-semitones pitch) 12))
>  (trans (vector-ref transpose-vector off)))
>    (if (eq? trans null)
> (begin (display "Warning: Mode mismatch")
> (display-music pitch))
>     (if (not (eq? trans 0))
>      (begin (set! pitch (ly:pitch-transpose pitch trans))
>       (ly:music-set-property! music 'pitch pitch))))))))
> music)


I usually do

   (let* ((a (blah))
          (b (if (is-a? a) (blub a)  #f)
          (c (if (is-b? b) (blab b) #f))
           ...
          )

--
  Han-Wen Nienhuys - [hidden email] - http://www.xs4all.nl/~hanwen


_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel
Reply | Threaded
Open this post in threaded view
|

Re: Transposing in modes??

Erik Sandberg
In reply to this post by Johannes Schindelin
On Wednesday 15 February 2006 03.49, Johannes Schindelin wrote:
> Hi,
>
> I always wanted to learn how to transform music with scheme, so I
> implemented half of it. If some of you experts could look at it and tell
> me what could be done more elegantly (Scheme is not my native language),
> and especially what needs to be done to make this easy to use, that would
> be super!

In addition to Han-Wen's comments, I can say the following:

Vectors, while constructs and side effects are not encouraged in Scheme; lists
and tail recursion are the preferred way of doing things. In general,
functions ending with ! should be avoided whenever possible. This is just a
convention, there is no penalty in performance or anything like that, so
there's no big point in rewriting your existing code other than for
educational purposes.

The "schemeish" way of writing your function, would probably be somethign
like:
- keep the different scales in ordinary lists, not vectors.
- Instead of the while loop in alter-mode, I'd probably have use fold, to
create a _list_ of pitch differences.
simple example: (fold (lambda (x y tail) (cons (- x y) tail)) '() list1 list2)
should, if list1='(a1 a2 a3) and list2='(b1 b2 b3), produce the list of
differences, something like
((- a1 b1) (- a2 b2) (- a3 b3))
- if it's essential for performance that a vector is used (i.e. if you use
direct indexing, rather than linearly searching the list) then the list can
be converted to a vector after it has been created.

--
Erik


_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel
Reply | Threaded
Open this post in threaded view
|

Re: Transposing in modes??

Johannes Schindelin
Hi,

On Thu, 16 Feb 2006, Erik Sandberg wrote:

> On Wednesday 15 February 2006 03.49, Johannes Schindelin wrote:
> > Hi,
> >
> > I always wanted to learn how to transform music with scheme, so I
> > implemented half of it. If some of you experts could look at it and tell
> > me what could be done more elegantly (Scheme is not my native language),
> > and especially what needs to be done to make this easy to use, that would
> > be super!
>
> In addition to Han-Wen's comments, I can say the following:

Completely forgot: Thank you, Han-Wen!

> Vectors, while constructs and side effects are not encouraged in Scheme;
> lists and tail recursion are the preferred way of doing things. In
> general, functions ending with ! should be avoided whenever possible.
> This is just a convention, there is no penalty in performance or
> anything like that, so there's no big point in rewriting your existing
> code other than for educational purposes.

Yes, I remembered that much from when I was forced to program in Lithp ;-)
However, in this case I wanted to do an indexed lookup, so the vector is
probably the right thing to do.

Next thing I'll do: Learn how to do tail recursion (I think I did that in
Lisp already, but don't remember how).

> (fold (lambda (x y tail) (cons (- x y) tail)) '() list1 list2)

I didn't know that function (fold).

> - if it's essential for performance that a vector is used (i.e. if you use
> direct indexing, rather than linearly searching the list) then the list can
> be converted to a vector after it has been created.

Problem is: I want to warn if a note was not translated, because it is not
in the original mode. Example: you want to translate { c4 c e e g g e2 }
to \minor, but mistakenly said that the source mode was \dorian. Then the
"e"s would not be in the source mode. So I actually construct a
translation mechanism for semitones.

Note: If it wasn't for the darned locrian scale, I would not need the
source mode at all (and therefore would not validate it anyway). Maybe I
return to that approach and just ignore locrian (source) modes.

Completely different question: I wanted to convert all this into a proper
music function. In the course, I found that the signature parsing is
less-than-elegant. In particular, there are only a handful permitted
signatures, which are hard-coded, such as "scm-scm-music". I gather that
this is needed in order to use flex/bison, but the different combinations
 of up to, say, 5 parameters could at least be generated, no?

In other words, would you gurus of lily look kindly upon an effort to
simplify the signature parsing?

I also found out -- the hard way -- that a definition like

        (def-music-function blabla (parser location key music)
                (ly:pitch? ly:music?) (...))

gets a signature "scm-music", which is wrong. Of course, I want to call
this function like in this manner:

        \blabla fis \relative c' { c d e f g }

Is my idea faulty? I do not particularly like scheme, as you might have
noticed, but at least it provides a good means to extend LilyPond without
recompiling it, and what is more important, in a form easily distributed
to others. But I still want to write the music using LilyPond syntax.

Ciao,
Dscho




_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel
Reply | Threaded
Open this post in threaded view
|

Re: Transposing in modes??

Erik Sandberg
On Thursday 16 February 2006 18.40, Johannes Schindelin wrote:
> Hi,
>
> Next thing I'll do: Learn how to do tail recursion (I think I did that in
> Lisp already, but don't remember how).
>
> > (fold (lambda (x y tail) (cons (- x y) tail)) '() list1 list2)
>
> I didn't know that function (fold).

It's a handy function that handles the tail recursion for you.

> > - if it's essential for performance that a vector is used (i.e. if you
> > use direct indexing, rather than linearly searching the list) then the
> > list can be converted to a vector after it has been created.
>
> Problem is: I want to warn if a note was not translated, because it is not
> in the original mode. Example: you want to translate { c4 c e e g g e2 }
> to \minor, but mistakenly said that the source mode was \dorian. Then the
> "e"s would not be in the source mode. So I actually construct a
> translation mechanism for semitones.

You can use arbitrary functions as arguments to fold. It might be sufficient
to replace the (cons (- x y) tail)) with a more complex expression, such as
the essential parts of the while loop. E.g., you could have a look at the
(begin ..) function.

> signatures, which are hard-coded, such as "scm-scm-music". I gather that
> this is needed in order to use flex/bison, but the different combinations
>  of up to, say, 5 parameters could at least be generated, no?
>
> In other words, would you gurus of lily look kindly upon an effort to
> simplify the signature parsing?

I think I could clean up the code quite much, it shouldn't be very difficult,
using one token type per arity. The hard part is if we want to make an
_arbitrary_ number of parameters possible (I think it's possible, but a bit
dirty -- AFAICS it requires that the parser sends faked argument separation
tokens to itself sometimes).

> I also found out -- the hard way -- that a definition like
>
> (def-music-function blabla (parser location key music)
> (ly:pitch? ly:music?) (...))
>
> gets a signature "scm-music", which is wrong. Of course, I want to call
> this function like in this manner:
>
> \blabla fis \relative c' { c d e f g }

The problem is that the parser can't distinguish between fis (pitch) and fis
(music expression). Further problems could arise in this case:
\blabla fis 4
is this a pitch followed by a number, or is it a single music expression
(fis4)?

> Is my idea faulty? I do not particularly like scheme, as you might have
> noticed, but at least it provides a good means to extend LilyPond without
> recompiling it, and what is more important, in a form easily distributed
> to others. But I still want to write the music using LilyPond syntax.

I'm looking into a way to create a language using def-music-function and
friends, in lilypond-style syntax (this would be a third party package, which
probably wouldn't be bundled with lilypond). However, I need to do a few
generalisations to the parser before I can write such package, and those
changes might not make it into the official lilypond distribution.

--
Erik


_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel
Reply | Threaded
Open this post in threaded view
|

Re: Transposing in modes??

Han-Wen Nienhuys
In reply to this post by Johannes Schindelin
Johannes Schindelin wrote:
> Completely different question: I wanted to convert all this into a proper
> music function. In the course, I found that the signature parsing is
> less-than-elegant. In particular, there are only a handful permitted
> signatures, which are hard-coded, such as "scm-scm-music". I gather that
> this is needed in order to use flex/bison, but the different combinations
>  of up to, say, 5 parameters could at least be generated, no?

Yes, but we do it on demand .. :)

Since we also allow \markup as a separate argument type, generating all
combinations quickly runs out of hand. In addition, it encourages people
to use different ordering of arguments.

Which ones are you missing?

> In other words, would you gurus of lily look kindly upon an effort to
> simplify the signature parsing?
>
> I also found out -- the hard way -- that a definition like
>
> (def-music-function blabla (parser location key music)
> (ly:pitch? ly:music?) (...))
>
> gets a signature "scm-music", which is wrong. Of course, I want to call
> this function like in this manner:
>
> \blabla fis \relative c' { c d e f g }
>
> Is my idea faulty?

Yes. You want a signature of music-music. LilyPond will interpret fis as
a short for fis4, a note (technically: an EventChord)

--
  Han-Wen Nienhuys - [hidden email] - http://www.xs4all.nl/~hanwen


_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel
Reply | Threaded
Open this post in threaded view
|

Re: Transposing in modes??

Nicolas Sceaux
In reply to this post by Johannes Schindelin
Johannes Schindelin <[hidden email]> writes:

> I always wanted to learn how to transform music with scheme, so I
> implemented half of it. If some of you experts could look at it and tell
> me what could be done more elegantly (Scheme is not my native language),
> and especially what needs to be done to make this easy to use, that would
> be super!

Here's how I'd do it, using a Common Lisp-like loop macro by Heinrich
Taube <http://nicolas.sceaux.free.fr/loop-guile.scm>. Using vectors is
not a bad thing. Neither is iterating (vs. recursing), IMHO loop is
eleguant and clearer. (hardly tested)

nicolas


#(begin
(load-from-path "loop-guile.scm")

(define (scale-semitones scale)
  "Get a vector of semitones for a given scale"
  (let ((semitones '(("ionian"     . #(0 2 4 5 7 9 11))
                     ("dorian"     . #(0 2 3 5 7 9 10))
                     ("phrygian"   . #(0 1 3 5 7 8 10))
                     ("lydian"     . #(0 2 4 6 7 9 11))
                     ("mixolydian" . #(0 2 4 5 7 9 10))
                     ("aeolian"    . #(0 2 3 5 7 8 10))
                     ("locrian"    . #(0 1 3 5 6 8 10)))))
    (let ((result (assoc scale semitones)))
      (if result
          (cdr result)
          (error "scale unknown: " scale)))))

(define (transpositions key-pitch source-scale target-scale)
  "Return the tranposition vector for transposing from source-scale
to target-scale. key-pitch is supposed to be a ly:pitch."
  (loop for source across (scale-semitones source-scale)
        for target across (scale-semitones target-scale)
        with transp-vector = (make-vector 12 #f)
        with key-offset = (ly:pitch-semitones key-pitch)
        do (vector-set! transp-vector
                        (modulo (+ key-offset source) 12)
                        (ly:make-pitch 0 0 (case (- target source)
                                             ((1) SHARP)
                                             ((-1) FLAT)
                                             (else 0))))
        finally (return transp-vector)))

(define (alter-mode-pitch music transposition-vector)
  (let ((pitch (ly:music-property music 'pitch)))
    (if (ly:pitch? pitch)
        (let ((transpo (vector-ref transposition-vector
                                   (modulo (ly:pitch-semitones pitch) 12))))
          (cond ((not transpo)
                 (display "Warning: Mode mismatch")
                 (display-music pitch))
                (else
                 (set! (ly:music-property music 'pitch)
                       (ly:pitch-transpose pitch transpo)))))))
  music)

(define (chord->pitch chord)
  "Find a pitch in a ChordEvent"
  (loop for event in (ly:music-property chord 'elements)
        if (eqv? (ly:music-property event 'name) 'NoteEvent)
        return (ly:music-property event 'pitch))))

alterMode =
#(def-music-function (parser location scales key music) (list? ly:music? ly:music?)
  "Transpose between types of scales"
  (let ((transposition-vector (apply transpositions (chord->pitch key)
                                     (map-in-order symbol->string scales))))
    (music-map (lambda (m)
                 (alter-mode-pitch m transposition-vector))
               music)))

normalScale = \relative c' { c4 d e f g a b c }

{
 \normalScale \break
 \alterMode #'(ionian phrygian) c \normalScale
}
_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel