Merry Christmas – I’m happy because I’ve fixed the envelope glitch.  In doing so I seem to have ditched the component model I spent ages setting up and put everything into a single note class, but it’s probably no bad thing as I want this to work on the iphone.

Speaking of which, I need to fix that version now – it was left in a slight state of disrepair as a result of my previous misguided efforts to fix the glitch.

So now that the glitch is dead, I’m onto the next glitch, and another redesign of my basic architecture.

I’d initially set it up so that there’s a trigger for each note.  Each trigger had an object attached which contained the state information for the note.  This works fine for short notes, but if the note is longer than the step interval, it’ll get cut off.

The current plan is to have a list of all active notes (better a pool eventually, but for now a list will do) and add to the list when a note is triggered.

Funny how my initial design is pretty much out the window…

Dead?  Not really.  Just temporarily quiet.

I’ve been busy with other things, mostly non-programming, but I’ve recently picked up the synth again.  After 3 or 4 months on inactivity, I’ve finally figured out what the little audio glitch was….  and it wasn’t what I thought.

I’d spent time thinking maybe the audio buffer size, audio settings or performance of the synth components would be to blame.  Turns out that wasn’t the case at all, and I’m kicking myself for not realising that.

The problem (which I haven’t actually fixed yet…) is that the volume isn’t being updated properly while filling the buffer.  This would only be a problem with the ADSR envelope, as it modified the volume of the input gradually.  I am currently updating the volume of components in one thread, while filling buffers in another.  This leads to a slight ’stepping’ in the audio at the start and end of a note – the glitch I was hearing.

The solution is probably to update the volume of components in the same thread as the audio data is processed.  I just need to figure out how to handle the timing now – I haven’t had a chance to sit down with it and concentrate yet, what with Christmas and all.

Hopefully Santa can deliver a fix on Christmas day.

I’ve been interested in the possibilities for HTML 5 for a while now, quite liking the (relative) ubiquity of flash, but disliking the integration with the browser.  It’s only now that HTML is becoming a viable alternative, with seemingly pretty decent support in Firefox 3.5 and the Chrome.

I’d been thinking it would be good to try and write a few vizualisation demos/toys in HTML 5 & Javascript, but haven’t got round to it yet.  These guys have.  Very impressive!

I thought if would be fun to get a game of life simulation running in the synth.  Sound isn’t the best – I really need to sort that out, but I did get to tidy things up a bit.  Anyway, here it is, enjoy.

After being finally getting very small (but perfectly formed) sound out of my iphone, sounding like a little synth, I showed it to my friend, who noticed the audio was coming out of the small ear speaker, rather than the speakers at the bottom.

Reading up on the audio buses used by RemoteIO, trying lots of tenuous and hopeful fixes, I found the solution.

It seems that if you enable both the input & output bus for RemoteIO, it uses the smaller of the speakers, presumably because when you enable the microphone you don’t want it picking up audio from the larger speakers at the bottom.

For some reason this logic escaped me for a while.

Anyway, after disabling the input bus, the larger speakers work fine.  Which is great.

After much fiddling, I’ve finally managed to get the synth working to an acceptable level on the iPhone.  I’ll describe my solution to the speaker problem later, but for now here’s a couple of nice videos of the iphone synth in action:

The Devil’s Own Music

Invaders Must Die

Recently, while trying to use RemoteIO on the iphone, I had to resort to using the device only for testing.  The simulator would give me a -66681 return code from AudioOutputUnitStart, whereas the device would work without problems.

Turns out theres a simple fix for that, detailed here.

Find UILocalizedIndexedCollation.h and change the line:
UIKIT_EXTERN @interface UILocalizedIndexedCollation : NSObject
to become
UIKIT_EXTERN_CLASS @interface UILocalizedIndexedCollation : NSObject

I made the change in both the iphone device and simulator SDKs (3.0 in my case).  I also reset my simulator.

One clean rebuild later and AudioOutputUnitStart worked perfectly.

Update: Actually, the error is back now and no combination of reseting, cleaning and rebuilding seems to fix it.  Crap.

Very nice parkour video shot in Sao Paulo.  Would love to try this stuff, but I don’t much like heights….  Nice excuse, and I’m sticking to it.

Not much visually different here, although the melody is better.

Under the hood, there’s been a bit of progress:

  • Load & configure synth components from a data file
  • Fixed some popping issues
  • Updated iphone version (although audio isn’t of great quality)

Up next:

  • Improve audio quality on iphone
  • Add audio to video recording

When working on a personal project, I have a habit of getting distracted and moving onto other interesting things.  So I’m quite happy to state that I’m still working on Synth (the synth?  I need a better name!)

I’ve been adding the ability to load the synth configuration from an xml file.  This allows me, of course, to specify and modify the synth setup without recompiling, allowing me to tweak things nice and quickly.  It better pay off, because it’s taken a bit more work than I thought it would to implement well!

At the end of the post, you can see an example of the current setup file.  The first chunk specifies the initial layout of the grid.  This is useful for quickly testing changes.  The next section specifies individual synth components (One thing to notice is that I’ve changed the envelope from a series of values corresponding to ADSR points, to a series of arbitrary points.)  The final section specifies, for each note (there are 12 in this synth), which component is at the top of its component ‘tree’ (the rootId) and which components should initiate any sound.

It’s definitely a first pass at the moment.  Apart from adding more components I could add delays to the initiators, for example.

Anyway, here’s the current setup:

<?xml version="1.0" encoding="UTF-8" ?>
<synth>
    <!-- Grid setup -->
    <initialSetup>
        <rows>
            <row>o...........</row>
            <row>............</row>
            <row>............</row>
            <row>...o........</row>
            <row>............</row>
            <row>............</row>
            <row>......o.....</row>
            <row>............</row>
            <row>............</row>
            <row>.........o..</row>
            <row>............</row>
            <row>............</row>
        </rows>
    </initialSetup>

    <!-- Components -->
    <components>
        <component type="oscillator" id="0" oscillatorType="sine" />

        <component type="mixer" id="1">
            <input id="0" amount="1"/>
        </component>

        <component type="envelope" id="2" inputId="1">
            <point time="0" volume="0.0"/>
            <point time="0.1" volume="0.9"/>
            <point time="0.2" volume="0.75"/>
            <point time="0.8" volume="0.65"/>
            <point time="1" volume="0"/>
        </component>
    </components>

    <!-- Systems -->
    <triggers>
        <trigger triggerId="0" rootId="2" >
            <initiator sourceId="0"/>
            <initiator sourceId="2"/>
        </trigger>
        <trigger triggerId="1" rootId="2" >
            <initiator sourceId="0"/>
            <initiator sourceId="2"/>
        </trigger>
        <trigger triggerId="2" rootId="2" >
            <initiator sourceId="0"/>
            <initiator sourceId="2"/>
        </trigger>
        <trigger triggerId="3" rootId="2" >
            <initiator sourceId="0"/>
            <initiator sourceId="2"/>
        </trigger>
        <trigger triggerId="4" rootId="2" >
            <initiator sourceId="0"/>
            <initiator sourceId="2"/>
        </trigger>
        <trigger triggerId="5" rootId="2" >
            <initiator sourceId="0"/>
            <initiator sourceId="2"/>
        </trigger>
        <trigger triggerId="6" rootId="2" >
            <initiator sourceId="0"/>
            <initiator sourceId="2"/>
        </trigger>
        <trigger triggerId="7" rootId="2" >
            <initiator sourceId="0"/>
            <initiator sourceId="2"/>
        </trigger>
        <trigger triggerId="8" rootId="2" >
            <initiator sourceId="0"/>
            <initiator sourceId="2"/>
        </trigger>
        <trigger triggerId="9" rootId="2" >
            <initiator sourceId="0"/>
            <initiator sourceId="2"/>
        </trigger>
        <trigger triggerId="10" rootId="2" >
            <initiator sourceId="0"/>
            <initiator sourceId="2"/>
        </trigger>
        <trigger triggerId="11" rootId="2" >
            <initiator sourceId="0"/>
            <initiator sourceId="2"/>
        </trigger>
    </triggers>
</synth>