Extempore doesn't like my long string

26 views
Skip to first unread message

Mook

unread,
Apr 6, 2015, 11:47:26 AM4/6/15
to extemp...@googlegroups.com
Hey guys,

i am a supernoob with extempore, just starting to learn. I am trying to modify an example from ben's website. I am trying to iterate over a string which is longer than his "Hello world" example. The sound always stops at the 49th character. I guess it's a memory problem somehow but i have no clue how to make extempore 'like' long strings. :D 
As far as i understand it the string is turned into a list which should be fine and it should't matter how many chars are in this list.
I also get the Bus Error: 10.
Working on a Mac with ST2 and Extempore 0.58.

Code hier eingeben

(define melody (for-each (lambda (c)
                       (- (char->integer c) 24))
                    (string->list "taatcacacctggtttgtttcagagccacatcacaaagatagagaacaacctaggtctccgaagggagcaagggcatcagtgtgctcagttgaaaatcccttgtcaacacctaggtcttatcacatcacaagttccacctcagactctgcagggtgatccaacaaccttaatagaaacattattgttaaaggacagcattagttcacagtcaaacaagcaagattgagaattaaccttggttttgaacttgaacacttaggggattgaagattcaacaaccctaaagcttggggtaaaacattggaaatagttaaaagac")))

; cycle through the string
(define loop
   (lambda (time pitch-list)
      (cond ((null? pitch-list) (println 'done))
            (else (play-note time fmsynth (car pitch-list) 80 1000)  
            (display (list melody))     
                  (loop (+ time (* *second* 0.3))                                    
                        (cdr pitch-list))))))

; start 
(loop (now) melody)...

Cheers,
Mook

Andrew Sorensen

unread,
Apr 6, 2015, 7:26:36 PM4/6/15
to extemp...@googlegroups.com
Hi,

Actually the string is working fine.  Try (println (length melody)) and you'll see that the melody is the correct length.  The problem is actually a little more idiomatic ;)

When you call play-note, you are immediately (i.e. regardless of 'time') adding a new note to an instrument. By default Extempore expects that these new notes are added relatively close to their 'actual' play time and by default has a cache limit of ... drumroll ... 48 ;) 

Effectively this cache limit of 48, in idiomatic extempore style, is a polyphony limit.  Once the cache is full any new notes coming in before old notes finish are simply dumped.

You could increase the cache size, but really what you want to do is to follow idiomatic extempore practice and call play-note closer to the actual play time.  Below is the small mod to loop function.

Was I listening to a rat or a mouse ;)

cheers,
Andrew.

; cycle through the string
(define loop
  (lambda (time pitch-list idx)
    (println 'playing idx)

    (cond ((null? pitch-list) (println 'done))
          (else
           (play-note time fmsynth (car pitch-list) 80 1000)
           (callback (+ time (* *second* 0.3)) 'loop (+ time (* *second* 0.3))
                     (cdr pitch-list)
                     (+ idx 1))))))





--
You received this message because you are subscribed to the Google Groups "Extempore" group.
To unsubscribe from this group and stop receiving emails from it, send an email to extemporelan...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Mook

unread,
Apr 7, 2015, 6:28:19 AM4/7/15
to extemp...@googlegroups.com
Hi Andrew,

thanks for clarifying. I am still not able to listen to the string, though. 
You were not listening to a mouse or rat but to the beginning gene string of the nasty Ebola virus. :D
As you can imagine the string is much longer than in the example I posted (original has >20k chars). I want to be able to listen to the whole string and modify the instrument i.e. after the 30th 'g' in the list.
Now, when I ran the code the first time i got the following message:

"VERY VERY BAD -bottom and top met in insert_treadmill!!!!!!
Out of memory!!. Catastrophic error!! free cells:0 

So  i changed the 'for-each' back to 'map' as it was in the example. Threw a Bus Error: 10

When i set the string to a shorter length(~900 chars) and just do a (println(melody)) it does log the list and then throws:
Abort trap: 6

I have no clue what's going on and the recompiling of the instruments.xtm every time is really time consuming. :D
Precompiling doesn't work for me it says: couldnt find xtmstd dynamic library.

Cheers,
Mook

Andrew Sorensen

unread,
Apr 7, 2015, 8:19:22 PM4/7/15
to extemp...@googlegroups.com
Hi,

As I'm sure you've noticed, you are running out of memory ;)

In general you want to avoid large lists in Scheme.  You are creating a very large list when you define melody.  So your problems aren't really with the string, but instead are with the creation of the list 'melody'.  A better approach is to simply read the characters straight out of the string and avoid making the melody list.  Like this example, which assumes that you have a string defined as 'sequence'.

(define sequence "taatcacacctggtttgt") ;; but much longer

; cycle through the string directly
(define loop_better
  (lambda (time dna idx end)
    (println 'playing idx)
    (if (< idx end)
        (let* ((c (string-ref dna idx))
               (pitch (- (char->integer c) 24)))
          (play-note time fmsynth pitch 80 1000)
          (callback (+ time (* *second* 0.02)) 'loop_better
                    (+ time (* *second* 0.02)) dna (+ idx 1) end))
        (println 'done))))

(loop_better (now) sequence 0 (length sequence))

Now FYI this will still cause problems with very large strings, because extempore's scheme interpreter doesn't handle very large string literals particularly well - and they (large string literals) are not a great idea in any case.  What you really want is to read the data straight out of an ascii text file.  Like this:

;; cycle through an ascii text file
(define loop_best
  (lambda (time dnafile idx)
    (println 'playing idx dnafile)
    (set-input-port dnafile)
    (let ((c (read-char)))
      (if (eof-object? c)
          (begin (println 'done)
                 (close-input-port dnafile))
          (begin
            (play-note time fmsynth (- (char->integer c) 24) 80 1000)
            (callback (+ time (* *second* 0.02)) 'loop_best
                      (+ time (* *second* 0.02)) dnafile (+ idx 1)))))))

(loop_best (now) (open-input-file "/tmp/dna.txt") 0)

Now you should be able to make the file "/tmp/dna.txt" as large as you like - fmsynth sonification of the human genome anyone?  Remember when you create the txt file that you don't want the start and end quotes (i.e. leave out the ") - just the characters.  And no carriage returns, new lines etc., just the sequence characters.

A couple of side notes:

If you want to keep using extempore you are definitely going to want to get precomp working.  Maybe send another new email to this list to get some help with that.

Your smaller string example "~900" should work just fine, but is crashing due to a syntax error in your code. What you want is either (println melody) or maybe (println (length melody)).  (println (melody)) is a syntax error (note that 'melody' is not a function that you can call).  Obviously it would be nicer for extempore to provide a nice friendly error message rather than crashing in flames, so maybe you could add a bug report to github for that one ;)  

Just submit the bug with the following example, which is all that is required to reproduce it.

(define sequence "taatcacacctggtttgtttcagagccacatcacaaagatagagaacaacctaggtctccgaagggagcaagggcatcagtgtgctcagttgaaaatcccttgtcaacacctaggtcttatcacatcacaagttccacctcagactctgcagggtgatccaacaaccttaatagaaacattattgttaaaggacagcattagttcacagtcaaacaagcaagattgagaattaaccttggttttgaacttgaacacttaggggattgaagattcaacaaccctaaagcttggggtaaaacattggaaatagttaaaagactaatcacacctggtttgtttcagagccacatcacaaagatagagaacaacctaggtctccgaagggagcaagggcatcagtgtgctcagttgaaaatcccttgtcaacacctaggtcttatcacatcacaagttccacctcagactctgcagggtgatccaacaaccttaatagaaacattattgttaaaggacagcattagttcacagtcaaacaagcaagattgagaattaaccttggttttgaacttgaacacttaggggattgaagattcaacaaccctaaagcttggggtaaaacattggaaatagttaaaagactaatcacacctggtttgtttcagagccacatcacaaagatagagaacaacctaggtctccgaagggagcaagggcatcagtgtgctcagttgaaaatcccttgtcaacacctaggtcttatcacatcacaagttccacctcagactctgcagggtgatccaacaaccttaatagaaacattattgttaaaggacagcattagttcacagtcaaacaagcaagattgagaattaaccttggttttgaacttgaacacttaggggattgaagattcaacaaccctaaagcttggggtaaaacattggaaatagttaaaa")


(define melody (for-each (lambda (c)
                       (- (char->integer c) 24))
                    (string->list sequence)))

(println (melody))


Cheers,
Andrew.


--

Mook

unread,
Apr 8, 2015, 3:30:09 AM4/8/15
to extemp...@googlegroups.com
Hi,

thank you so much. With the last example it worked. :D
Nasty virus sounds nasty with fuzz bass.

Thanks for your time, very much appreciate it. 
Now on to more Extempore!

Cheers,
Mook

Pierre-Yves Gérardy

unread,
Apr 15, 2015, 4:42:23 PM4/15/15
to extemp...@googlegroups.com
This is slightly off topic for the list: where can I find the full
sequence? I'd like to play with DNA visualizations.
—Pierre-Yves
Reply all
Reply to author
Forward
0 new messages