1 (edited by Shiru 2017-02-09 12:34:54)

Topic: A Python script to convert XM modules into something

A little project I just made - a small Python library to parse XM modules and extract song data from them easily. Comes with two example scripts. One of them just prints out notes, the other is a straight port of the xm2octode converter that yields identical output.

Good: once you have Python installed in your system, you can easily edit, develop, modify the conversion scripts without need of having a compiler around, using popular modern scripting language. Handy for quick prototyping. Also cross-platform.

Bad: it is (edit: was) really slow, a large Octode module takes a few seconds to convert even on a quad core i5.


Sure, that's not a game changer or anything special, but yet another way of doing things.



Note: I'm personally not a big fan of Python, but use it occasionally. So I have no idea how good Python code should look like. I did it so it just works, not pretty.

Post's attachments

xmlib_python.zip 3.52 kb, 3 downloads since 2017-02-09 

You don't have the permssions to download the attachments of this post.

Re: A Python script to convert XM modules into something

Ah, excellent. I've been using my own (C++) lib for quick prototyping of XM converters since a while so I have no acute need for this, but mine is very badly designed so I can't publish it as a stand-alone library. So it's nice to have a clean and well-designed backup plan.

I'm surprised it's so slow, though. I mean Python is not exactly fast, but it shouldn't take that long. I took the liberty of running the script through cProfile and this is what I got:

         5450 function calls in 7.201 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.021    0.021    7.201    7.201 convert_octode.py:3(<module>)
        1    0.000    0.000    0.000    0.000 genericpath.py:55(getsize)
        1    7.138    7.138    7.138    7.138 xmlib.py:10(XM)
        4    0.000    0.000    0.000    0.000 xmlib.py:133(get_order)
        2    0.000    0.000    0.000    0.000 xmlib.py:140(get_pattern_length)
     1024    0.002    0.000    0.002    0.000 xmlib.py:148(get_note)
     1024    0.002    0.000    0.002    0.000 xmlib.py:153(get_instrument)
     1024    0.002    0.000    0.002    0.000 xmlib.py:158(get_volume)
     1040    0.002    0.000    0.002    0.000 xmlib.py:163(get_effect)
     1025    0.004    0.000    0.004    0.000 xmlib.py:168(get_parameter)
       15    0.000    0.000    0.000    0.000 xmlib.py:26(read_word)
        3    0.000    0.000    0.000    0.000 xmlib.py:29(read_dword)
        1    0.029    0.029    0.029    0.029 xmlib.py:32(load)
        1    0.000    0.000    7.138    7.138 xmlib.py:4(<module>)
        1    0.000    0.000    0.000    0.000 {len}
        2    0.000    0.000    0.000    0.000 {method 'append' of 'array.array' objects}
        1    0.000    0.000    0.000    0.000 {method 'close' of 'file' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        1    0.000    0.000    0.000    0.000 {method 'fromfile' of 'array.array' objects}
        1    0.000    0.000    0.000    0.000 {open}
        1    0.000    0.000    0.000    0.000 {posix.stat}
      276    0.001    0.000    0.001    0.000 {range}

I think the main bottleneck happens with setting up the arrays on constructing XM class object. I tried with XMs of varying complexity, there is almost no change in execution time. So the conversion functions aren't the problem, in any case. Not sure how that can be rectified. One could of course read the song parameters first and only set up the necessary amount of arrays afterwards, but I have a feeling that that doesn't tackle the problem at its root.

Hmm, this looks interesting, especially the last answer. I'm not a Python coder at all though.

3 (edited by Shiru 2017-02-09 11:10:23)

Re: A Python script to convert XM modules into something

Thanks a lot, I wouldn't even think that the bottleneck is the array allocation. I changed the script a bit, replaced multi-dimensional list with one-dimensional, and now it takes just a second to convert a module, which is good enough, I think.

The improved version re-attached to the first post.