SYNTHINGS is a digital synthesizer development platform that I've been building.

Tune editor (part 3)

jason | 15 January, 2011 23:21

Today, I went in a bit of a circle with the memory allocation for the tune.

I started off in two minds as to the best approach for this. I need to have it quick to update in the screen, and easy to insert events in the middle of the data. I've got 32K of SRAM assigned to the tune arrangement, and only 6K of RAM in the PIC to hold it in (this memory is given to the pattern editor when you're editing the pattern).

I could split the memory into 16 equal chunks (one for each voice), but then I'd limit myself to 512 pattern events per voice (each pattern placement takes 4 bytes - two for the start location, and another two for the pattern number) - and if you were doing an 8 voice tune, that's half the memory wasted.

I initially decided to have all the tune pattern arrangement to be linear, and sorted by the play time, so drawing the pattern would be easy. In order to make it easy to insert items in memory, I would split the 32K into 256 128-byte chunks, and use a double-linked list to make it easier to insert data in the middle of other data. Memory would get fragmented, so a defragmentation scheme was done.

While writing the insertion code, I decided that this was way to complicated. I had a 128-byte memory allocation routine in the pattern editor, and another one in the tune - both doing similar, yet different things.

I then decided to merge the memory chunks together (they were already immediately after each other), and have the pattern and tune use a common memory allocation system.

The memory code was removed from the pattern editor, and placed in its own memory handler, and I changed the memory code to have a concept of objects. An object would be a pattern, or a voice line in the tune editor. An object would need a number of blocks depending on how much memory the object needs. Each block allows 124 bytes of data (the other 4 are used to link to the next block, the parent object, and how many bytes are used in the block.

The memory transfer (load and save) functions were a bit more lower level than the pattern ones (which needed to insert the pattern name, length and colour in the first block). This meant that the pattern save and load now needed to compress and decompress while knowing that the pattern information needed to be at the start of the memory block.

On startup, the tune editor would create 16 objects - none of which would use any memory. When you create a new pattern, then a new object is created. As an extension, if a new pattern is created, and you abort without saving, then it'll free the object back.

With the new memory arrangement, there's 3360 available blocks and objects (which is up from the 3072 patterns). I can increase this slightly (there's an area of memory used to store the object start addresses, and I've got more memory allocated there than I need).

The displaying of the tune will be a little more complex than before, but hopefully it shouldn't be too bad. The memory footprint hasn't changed that much (an extra 136 bytes of ROM, and 32 bytes of RAM):

Program Memory  [Origin = 0x200, Length = 0x2aa00]

section                    address   length (PC units)   length (bytes) (dec)
-------                    -------   -----------------   --------------------
.text                        0x200              0x136e          0x1d25  (7461)
.const                      0x156e              0x26d6          0x3a41  (14913)
.text                       0x3c44              0xc4be         0x1271d  (75549)
.dinit                     0x10102               0x24c           0x372  (882)
.text                      0x1034e               0xde0          0x14d0  (5328)
.isr                       0x1112e                 0x2             0x3  (3)

                     Total program memory used (bytes):        0x196c8  (104136) 39%

Data Memory  [Origin = 0x800, Length = 0x7800]

section                    address      alignment gaps    total length  (dec)
-------                    -------      --------------    -------------------
.nbss                        0x800                   0           0x9ea  (2538)
.ndata                      0x11ea                   0             0x2  (2)
_03774ee04d2cd01c           0x11ec                   0           0x200  (512)
_037770704d2cd01c           0x13ec                   0           0x200  (512)
.nbss                       0x15ec                   0           0x314  (788)
.ndata                      0x1900                   0            0x86  (134)
.nbss                       0x1986                   0            0xa0  (160)
.ndata                      0x1a26                   0            0x20  (32)
.nbss                       0x1a46                   0            0x38  (56)
.ndata                      0x1a7e                   0            0x22  (34)
.nbss                       0x1aa0                   0            0x1c  (28)
.ndata                      0x1abc                   0             0x8  (8)
.nbss                       0x1ac4                   0            0x1a  (26)
.ndata                      0x1ade                   0             0x2  (2)
.nbss                       0x1ae0                   0             0x4  (4)
.ndata                      0x1ae4                   0             0x4  (4)
.nbss                       0x1ae8                   0             0x2  (2)
.ndata                      0x1aea                   0             0x2  (2)
.data                       0x1aec                   0           0x106  (262)
.dconst                     0x1bf2                   0             0x8  (8)
.data                       0x1bfa                   0             0xa  (10)
.bss                        0x1c04                   0             0x4  (4)
.data                       0x1c08                   0             0x2  (2)
.heap                       0x1c0a                   0          0x2000  (8192)

                        Total data memory used (bytes):         0x340a  (13322) 43%

Dynamic Memory Usage

region                     address                      maximum length  (dec)
------                     -------                      ---------------------
heap                        0x1c0a                              0x2000  (8192)
stack                       0x3c0a                              0x43f6  (17398)

                        Maximum dynamic memory (bytes):         0x63f6  (25590)

Tomorrow, I'll need to start arranging the pattern - and maybe have a go at loading and saving whole tunes. There's nothing worse than creating a wonderful test tune and not being able to save it...

Powered by LifeType - Design by BalearWeb and Jason Tribbeck
Copyright © 2010 | | Jason Tribbeck
All trademarks are the property of their respective owners