Loopy Pro: Create music, your way.

What is Loopy Pro?Loopy Pro is a powerful, flexible, and intuitive live looper, sampler, clip launcher and DAW for iPhone and iPad. At its core, it allows you to record and layer sounds in real-time to create complex musical arrangements. But it doesn’t stop there—Loopy Pro offers advanced tools to customize your workflow, build dynamic performance setups, and create a seamless connection between instruments, effects, and external gear.

Use it for live looping, sequencing, arranging, mixing, and much more. Whether you're a live performer, a producer, or just experimenting with sound, Loopy Pro helps you take control of your creative process.

Download on the App Store

Loopy Pro is your all-in-one musical toolkit. Try it for free today.

Any apps that can read Ableton .als files?

1356

Comments

  • @rs2000 nice. As I had thought. Thank you. No scrolling and less mistakes typing 👍

  • It would be great if someone could add this info to the wiki

    https://wiki.audiob.us

    It will help folks find the info in the future and also makes it possible to keep the info current as things develop.

  • edited December 2019

    Here's an update with more readable output, summarizing what the script has found in the Ableton export.

    import xml.etree.ElementTree as ET
    from midiutil import MIDIFile
    
    infile = "ableton_test_xml_2.txt"
    outfile = "testfile_01.mid"
    
    track    = 0
    channel  = 0
    time     = 0    # In beats
    duration = 1    # In beats
    tempo    = 60   # In BPM
    volume   = 100  # 0-127, as per the MIDI standard
    
    #preparing XML tree
    tree = ET.parse(str(infile))
    root = tree.getroot()
    
    #getting the tempo/bpm (rounded) from the Ableton file
    for master in root.iter('Tempo'):
        for child in master.iter('FloatEvent'):
            tempo = int(float(child.get('Value')))
            #print('tempo: ', tempo)
    
    #get amount of tracks to be allocated
    for tracks in root.iter('Tracks'):
        numTracks = len(tracks.getchildren()) + 1
    
    #Opening the target MIDI-file
    MyMIDI = MIDIFile(numTracks)  # One track, defaults to format 1 (tempo track is created automatically)
    MyMIDI.addTempo(track, time, tempo)
    
    for tracks in root.iter('Tracks'):
            for miditracks in tracks.iter('MidiTrack'):
                print('\nMIDITRACK ', track)
                track = track + 1
    
                #getting the key(s) per miditrack
                for keytracks in miditracks.iter('KeyTrack'):
                    for child in keytracks.iter('MidiKey'):
                        keyt = int(child.get('Value'))
                        print('key:', str(keyt) + ',', end=' ')
    
                        #getting the notes
                        mycount = 0
                        for midiData in keytracks.iter('MidiNoteEvent'):
                            tim = midiData.get('Time')
                            dur = midiData.get('Duration')
                            vel = midiData.get('Velocity')
                            #print(tim, dur, vel)
                            
                            #writing the actual note information to file
                            #MIDIFile.addNote(track, channel, pitch, time, duration, volume, annotation=None
                            #MyMIDI.addNote(track, channel, keyt, mycount, float(dur), int(vel))                        
                            MyMIDI.addNote(track, channel, keyt, float(tim), float(dur), int(vel))
                            mycount = mycount + 1
                        print('processed',int(mycount),'note events')
    
    with open(str(outfile), "wb") as output_file:
        print('Writing', int(track), 'tracks to', str(outfile), '...', end=' ')
        MyMIDI.writeFile(output_file)
        print ('done.')
    
  • @espiegel123 I'll leave that to @MrBlaschke because he's the author.

  • Very usefull script, thanks a lot for showcasing Pythonista.

    I use Python at work, but didn‘t yet look for python on the iPad. But having files access, midi capabilities and gui elements it seems ideal to solve conversion problems. Just pressed the ‚buy‘ button :)

    Regarding the wiki, i can offer help with the page and its tags as i have lately invested some time in structuring and unifying the tags.

  • Patterning 2 has Ableton Live Export with midi, so you can use those als files too 😊

  • @_ki said:
    Very usefull script, thanks a lot for showcasing Pythonista.

    I use Python at work, but didn‘t yet look for python on the iPad. But having files access, midi capabilities and gui elements it seems ideal to solve conversion problems. Just pressed the ‚buy‘ button :)

    Regarding the wiki, i can offer help with the page and its tags as i have lately invested some time in structuring and unifying the tags.

    That'd be great, thanks!
    If I find the time, I'll have a look at making @MrBlaschke's script even more user-friendly, Pythonista can do so much more than that :smiley:

  • Since Pythonista supports the share extension, one could extend the script so that „Convert ALS to MIDI“ is available directly in the share menu in the Files app :) One then should write the midi output file to the same path.

  • @_ki said:
    Since Pythonista supports the share extension, one could extend the script so that „Convert ALS to MIDI“ is available directly in the share menu in the Files app :) One then should write the midi output file to the same path.

    Someone please do this D:

  • @_ki
    I would be very happy if you could do the WIKI thing. That would be very helpful. Thank you in advance.

    And, yes, it could be extended like you said with the „sharesheet“ or combine it with the „Shortcuts/Workflow“ app.
    I have done that with other scripts i use daily.

    Glad people find use in this little experiment.

  • Just lost several hours investigating in Pythonista B)

    The objectiveC interface to native IOS stuff is super interesting. By modifying examples found on the web (and lots of trial and error) I managed to output a list of all installed AUs.

    To loosen up the everlasting failure i looked around at other stuff like using the IOS speech synthesizer with all its installed voices from a dialog getting funny dialects when supplied with foreign words (BTW: IOS 13 supports writing the ouput to a file) and drawing hardware supported 3D scenes with light and shadow using SceneKit.

    Time flew by, i was too distracted to work on the wiki page or even read the forum :)

  • Pythonista is great, doing a Python course at the moment and using the phone for most of the project things to the horror of the instructor.

    It all works and my eyes are much happier!

  • edited December 2019

    @gonekrazy3000 said:

    @_ki said:
    Since Pythonista supports the share extension, one could extend the script so that „Convert ALS to MIDI“ is available directly in the share menu in the Files app :) One then should write the midi output file to the same path.

    Someone please do this D:

    I've just done that.
    Including the capability of reading the exported zip archive directly.

    The workflow looks like this (simple example):





  • Save the script to your folder of choice inside Pythonista.
    Now install the script as an extension in order to find it in the
    "Open in..." > "Run Pythonista Script" dialog:
    Tap "Run Pythonista Script", tap the bottom large "+" icon, choose "Run Script" and choose the one you've just created.

    I haven't tried yet but I don't see a reason why this shouldn't work with other apps too because the script generally looks for the first ".als" file in the exported zip archive, no matter what the song is called or how the folder structure is inside.

    Here's the code:

    # Ableton MIDI clip zip export to MIDI file converter
    # Original script by MrBlaschke
    # Usability enhancements by rs2000
    # Dec 8, 2019
    #
    # Original request and idea by Svetlovska
    
    import xml.etree.ElementTree as ET
    import xml.etree as XTree
    from midiutil import MIDIFile
    import console
    import io
    import appex
    import ui
    from zipfile import ZipFile
    from time import sleep
    
    def main():
      if not appex.is_running_extension():
        print('This script is intended to be run from the sharing extension.')
        return
      
      # Catch zip file from external "Open in..." dialog
      #ablezip = appex.get_file_path()
      with ZipFile(appex.get_file_path(), 'r') as ablezip:
          #print(ablezip.namelist())    # Enable this to show the contents of the zipped export
          print('Found:', end=' ')
          string = ('.als')
          
          # Get the first .als file in the zip archive
          for s in ablezip.namelist():
              if string in str(s):
                  print(str(s))
                  #alsfile = ablezip.open(str(s), mode='r', pwd=None)
                  #with ablezip.open(str(s)) as myfile:
                  infile = ablezip.extract(str(s))
                      #infile = myfile.read()
                      #print ('\n',str(infile))
                      
     ## infile = "ableton_test_xml_2.txt"
      outfile = "testfile_01.mid"
      
      track    = 0
      channel  = 0
      time     = 0    # In beats
      duration = 1    # In beats
      tempo    = 60   # In BPM
      volume   = 100  # 0-127, as per the MIDI standard
      
      # Rather parse the file because parsing strings will not clean up bad characters in XML
      tree = ET.parse(str(infile))
      root = tree.getroot()
      
      #getting the tempo/bpm (rounded) from the Ableton file
      for master in root.iter('Tempo'):
          for child in master.iter('FloatEvent'):
              tempo = int(float(child.get('Value')))
              #print('tempo: ', tempo)
      
      #get amount of tracks to be allocated
      for tracks in root.iter('Tracks'):
          numTracks = len(tracks.getchildren()) + 1
          print('Found',str(numTracks),'tracks')
      
      #Opening the target MIDI-file
      MyMIDI = MIDIFile(numTracks, adjust_origin=True)  # One track, defaults to format 1 (tempo track is created automatically)
      MyMIDI.addTempo(track, time, tempo)
      
      # Process every MIDI track found
      for tracks in root.iter('Tracks'):
              for miditracks in tracks.iter('MidiTrack'):
                  print('\nMIDITRACK ', track)
                  track = track + 1
      
                  #getting the key(s) per miditrack
                  for keytracks in miditracks.iter('KeyTrack'):
                      for child in keytracks.iter('MidiKey'):
                          keyt = int(child.get('Value'))
                          print('key:', str(keyt) + ',', end=' ')
      
                          #getting the notes
                          mycount = 0
                          for midiData in keytracks.iter('MidiNoteEvent'):
                              tim = midiData.get('Time')
                              dur = midiData.get('Duration')
                              vel = midiData.get('Velocity')
                              #print(tim, dur, vel)
                              
                              #writing the actual note information to file
                              #MIDIFile.addNote(track, channel, pitch, time, duration, volume, annotation=None
                              #MyMIDI.addNote(track, channel, keyt, mycount, float(dur), int(vel))                        
                              MyMIDI.addNote(track, channel, keyt, float(tim), float(dur), int(vel))
                              mycount = mycount + 1
                          print('processed',int(mycount),'note events')
      
      # Write the resulting MIDI file
      with open(str(outfile), "wb") as output_file:
          print('Writing', int(track), 'tracks to', str(outfile), '...', end=' ')
          MyMIDI.writeFile(output_file)
          output_file.close()
          
          # Open the MIDI file in your app of choice :)
          console.open_in(str(outfile))
          print ('done.')
        
    if __name__ == '__main__':
        main() 
    
  • BTW, I've used Pythonista's "Primaries_Expand" icon and a reddish background because to me it looks much like a MIDI file export
    with notes on a piano roll.

  • edited December 2019

    Great enhancements in „un-nerdying“ and making it more userfriendly. Well done @rs2000

    I see that not the latest version of the Codebase was used. I had it to extract and set the tracknames in the latest version. Maybe I can implement it again later today using the posted codebase.

  • @MrBlaschke said:
    Great enhancements in „un-nerding“ and making it more userfriendly. Well done @rs2000

    I see that not the latest version of the Codebase was used. I had it to extract and set the tracknames in the latest version. Maybe I can implement it again later today using the posted codebase.

    Oops... thank you!

  • @rs2000 When i run your script extension with an als file exported by Gadget, i get a BadZipFile exception "File is not a zip File". I checked the exported test.als on my desktop computer and could unzip it with 7zip and retrieve the XML that didn't have any file extension.

  • edited December 2019

    @_ki @rs2000 and all others:

    Here is an update with a lot of new features - if one can call them like that:

    • the error @_ki reported above is no longer existing - the script handles pure ALS and ZIP files completely automatic (Just share any file - non accepted/invalid files will also be recognized)
    • We no longer create a MID file inside of Pythonista - script works with self-deleting, non visible „temp file system“
    • Includes the Share Sheet refinements from @rs2000
    • No longer creates 1 to many empty tracks at the top of the resulting MID file
    • The tracknames are extracted and automatically generated to the corresponding MIDI track in the generated file
    • lots of cleanup and refinements

    removed code - new version along this thread

  • Ok, this was interesting enough for me to buy Pyhtonista.

    I tried to follow a few steps posted but I’m not familiar with any of this process so may have missed a step.

    Created a folder and new Script in P3 app and copy/pasted the code above into it. Didn’t see a save option and also didn’t see the red icon when trying to share from Groovebox.

    I’m here.... what did I miss? Cheers 👍

  • edited December 2019

    @SpookyZoo
    You don’t share from within Pythonista.
    You go to your source file (in our case the ABL or ZIP file) and share that into Pythonista - exactly to your script „Stu GBX2.py“.
    Then follow the steps from @rs2000 from a little bit above: https://forum.audiob.us/discussion/comment/723189/#Comment_723189

    The red icon and the name „Groovebox to MIDI File“ in his examples are self defined. You can do that when you share a file to Pythonista and press the „EDIT“ button

    There you can select an icon and the script you want to assign to the share-button.

  • edited December 2019

    Cool. Thanks for the additional tips.

  • Ok. I could make a video tomorrow - if needed.

  • edited December 2019

    @MrBlaschke said:
    Ok. I could make a video tomorrow - if needed.

    Although I did just get it working, If you get the chance to make a quick screencast that could be really helpful as a reference for the thread. Thanks and gratitude. 👍

    This info is brilliant btw....

  • _ki_ki
    edited December 2019

    @MrBlaschke Nice and clean update :)

    But - it still crashes on my ALS file exported from gadget. Looking at the console output, it detected a 'direct Ableton ALS file' and the xml parser crashes on the the first token.
    Gadgets .als are still in compressed format, according to 7zip its a 'gzip' file thats why the zipfile module doesn't work. Luckily Pythonista offers gzip functionality, so you probably also need to add that case to the start of the script.

    .

    BTW: I added a wiki page for the Pythonista: ALS to MIDI converter script and another one for general info about Ableton Link and Live Set file export .

  • @_ki
    I do not own Gadget - could you provide a Gadget gzip file to me so i can test?

  • Great work! Thanks to all the boffins for getting this going. 👍

    @_ki said:
    @MrBlaschke Nice and clean update :)

    But - it still crashes on my ALS file exported from gadget. Looking at the console output, it detected a 'direct Ableton ALS file' and the xml parser crashes on the the first token.
    Gadgets .als are still in compressed format, according to 7zip its a 'gzip' file thats why the zipfile module doesn't work. Luckily Pythonista offers gzip functionality, so you probably also need to add that case to the start of the script.

    .

    BTW: I added a wiki page for the Pythonista: ALS to MIDI converter script and another one for general info about Ableton Link and Live Set file export .

  • @_ki said:
    @MrBlaschke Nice and clean update :)

    But - it still crashes on my ALS file exported from gadget. Looking at the console output, it detected a 'direct Ableton ALS file' and the xml parser crashes on the the first token.
    Gadgets .als are still in compressed format, according to 7zip its a 'gzip' file thats why the zipfile module doesn't work. Luckily Pythonista offers gzip functionality, so you probably also need to add that case to the start of the script.

    .

    BTW: I added a wiki page for the Pythonista: ALS to MIDI converter script and another one for general info about Ableton Link and Live Set file export .

    Great! You are a hero.

  • @MrBlaschke said:
    Great enhancements in „un-nerdying“ and making it more userfriendly. Well done @rs2000

    I think you may have increased Pythonista's app store sale this month with the code you created.

  • @MrBlaschke No problem, i attached a zip containing the generated ALS and the direct midi export of the three tracks.

    • Track 1 (Gladstone) are 4 bars of a simple drumpattern
    • Track 2 (Warzawa) are 4 bars with chords and additional filter automation
    • Track 3 (Berlin) are 4 bars with some mono synth notes and vibrato and pitchbend data on the long note.

    Maybe you could also try to grab the vibrato (should be CC-1 modwheel) and pitchbend data `from the ALS.

Sign In or Register to comment.