551

(135 replies, posted in Sinclair)

As far as singing speech synths go, there's of course tavzx: https://www.youtube.com/watch?v=KkZKDJwwb2o
I agree, would be interesting to have something like this in an actual music engine. However, I'd be more interested in implementing actual formant synthesis. I've done a sample-based speech synth a couple of years ago (also with variable pitch btw), it's pretty boring work imo.

I think some MIDI solution would be preferable because of its potential impact. Would it be possible to ditch the Arduino MIDI shield and just decode the MIDI messages directly on the Arduino, using one of the digi ports? It would cause some additional load on the CPU of course, but on the other hand there's no need to load sequence/pattern data any more. As far as instruments go, yes, they could be pre-defined patches, but the engine should also make best use of the available standard Control Change messages, which could be linked to settings of duty, vibrato, etc.

Impressive! Never managed to port this engine to TI because of the interrupts. But I guess the variable timer interrupts on the Arduino come in very handy in that case.

So, what's next, any plans for a custom Arduino engine written in C?

554

(15 replies, posted in Other Platforms)

Was just reading about this guy's troubles, so a software issue seems quite possible.

Perhaps it's easier to disable auto-reset until you've found the culprit?

555

(4 replies, posted in Sinclair)

Cheers Tufty wink Both channels are identical, so yes, you can use two SID voices at once. Click drums are synthesized. The drum synth is less advanced than in Phaser1 or Phaser2, but nevertheless you can pass an 8-bit parameter to change their sound. On kicks, you can set the starting pitch, and on click noise, you can select one of two fixed pitches, and set the volume. For really advanced trickery, a completely different drum synth could be swapped in via the "arbitrary code execution" feature, which allows you to literally change any aspect of the engine at runtime. Furthermore, you can of course fake drums via table fx - noise combines nicely with volume envelopes, too, for example.

556

(7 replies, posted in Other Platforms)

Wow Shiru, looks like you're on a roll!

Since Arduino 1-bit seems all the rage now, I thought I'd give the avra+avrdude combo a try. Works like a charm, successfully produced a beep in asm!

Indeed, 16 MHz is a lot, especially considering the instructions are also super-fast. Guess I'll have to get used to writing purposefully slow asm code. Or just write complex enough routines, heh. Well, for now I'll leave things at "yay, my toolchain works" but next time I get bored with my other projects I might actually go and try writing a dedicated routine for this thing.

Edit: Wow, I just found out that ATmega has a fixed-length, 2-cycle MULtiply instruction. This should make it possible to implement stuff like 1-bit Phase distortion, perhaps even FM.

Thanks! Looks like even someone totally inept at soldering like me can construct this.

558

(10 replies, posted in Other Platforms)

Awesome! Listening to the demo tune right now, and I can confirm there's no noticable artifact/carrier noise on my setup.

Well, would be great if this gets some exposition on the Arduino forums. If there's enough interest, we might even consider opening a special Arduino sub-board on here.

559

(4 replies, posted in Sinclair)

esoteric music plays... Imagine... a beeper engine that can play almost any sound ever played by any beeper engine. An engine that transcends the boundaries between data and code by enabling you to modify any part of the player at runtime. An engine that will revolutionize the way we make beeper mu-record scratch

Ok guys, let's cut the crap wink Here's my latest engine. It picks up where wtbeep left off, and combines the modular concept of it with the simplified volume generation technique I posted for the saw wave demo here. It's insanely powerful, but unfortunately, composing music for it will also drive you insane, as there's no editor available and the data format is rather complex. In theory, the latest MDAL should be able to support the engine, but I need to implement mixing of strings and numeric values before it really makes sense to try.

Anyway, have a quote from Uncle Readme.

BM-1 is an experimental sound routine for the ZX Spectrum beeper. It features a
highly versatile synthesis core that can be modified during runtime, which
makes it possible to generate a near-endless range of different sounds.


Features include:

- 2 tone channels, 12-bit or 15-bit frequency dividers
- patches: on-the-fly modifications of the synthesis algorithm
- volume control (8 levels per channel, availability depends on patch)
- tables: change pitch and fx parameters per tick
- functions: arbitrary code execution/modification once per tick
- customizable click drums
- per-step tempo control
- compact player size (375 bytes, can be reduced by disabling features)
- optimized data format

With patches, you can produce

- variable duty cycles
- phatness/harmonics control
- fake chords
- bytebeat-like glitches
- SIDsound (duty sweep)
- PFM (classic pin pulse sound)
- noise

source: https://github.com/utz82/ZX-Spectrum-1- … aster/bm-1
direct dl: https://github.com/utz82/ZX-Spectrum-1- … p?raw=true


This will be more or less my last engine for the ZX beeper, until a some fundamentally new techniques are discovered. I still have two ideas I want to put into practise, but these will be rather simple (one is an engine with vibrato support, and one is applying the volume technique from BM-1 to wavetables, which will save a huge amount of code compared to the multi-core technique). Not sure when I'll do those, if somebody else wants to pick up these ideas in the meantime, that's fine with me. No worries though, I have no intentions of abandoning the Spectrum, but I have some other unfinished projects that I want to focus on in the coming months. Stay tuned.

Edit: Added an example patch for PFM sound.

560

(37 replies, posted in Other Platforms)

Alright, sucessfully uploaded garvalf's hex file with avrdude. The ELF doesn't run however, avrdude claims it's not valid. So I guess it's some intermediate thingy that's not meant to be uploaded. Well, no problem for now.

Good to see that the avr-gcc is reasonably efficient. Also, I still think it's very nice that you get annotated output with avr-objdump.

Still not sure if I want to install the latest IDE, especially not alongside the older install. If it were all contained in a standalone Java app then sure, but afaik it installs a ton of other stuff, namely all the avr tools. And I'm afraid checkinstall won't do the trick on this one.

I'm sorry but I don't have any octode demo tunes to offer. Have several snippets laying around but never managed to actually complete a song with it yikes

So, guys, excuse my absolute electronics ignorance, but what would be the most reasonable approach to adding a line-out to this thing? Right now I have a PC speaker attached like garvalf, with some resistor thrown in for good measure.

561

(37 replies, posted in Other Platforms)

I feel your pain, man. Arduino documentation is good but only as long as you're going to do things their way.

Anyway, dug out my Uno clone today and tried to run Octode, but as expected the ELF compiled with 1.0.5 IDE doesn't work. Could you share your ELF, so I can try to upload it directly?

562

(37 replies, posted in Other Platforms)

Well, you have a point. I'll think about it more... perhaps write some simple tool that will convert AVRA source to Arduino syntax.

Anyway, I tried compiling arduino_octode, but I was getting some errors. I think it's because I have a very outdated version (1.0.5, thanks Debian) - it doesn't like PROGMEM and NULL. I got it to compile with defining NULL as 0 and PROGMEM as nothing, but that is not the correct way to do it afaik. I should probably replace the Debian version with a newer one, but given that the sources are like 90 MB I'm not too inclined to do it right now, as it would probably take half a day to compile them on my machine.

Anyway, I was able to extract the resulting ELF file and disassemble it. avr-objdump outputs a pretty nice, commented listing, so I'd say give it a try. Or, if you're having problems with it, send me the ELF files (ctrl-f arduino_octode.cpp.elf) and I'll send you back the asm listings.

563

(37 replies, posted in Other Platforms)

Wouldn't it be possible to link Arduino C code against a pre-compiled library? Then such a library could be written in asm. That was actually what I was intending to do with the Z80 emulation.

564

(37 replies, posted in Other Platforms)

Wow, I wouldn't have thought that it's possible to pull this off in C at all. I personally have no interest in programming this thing in C considering the beauty of the AVR m'code instruction set, but still, nice to see it works and is efficient enough.

Regarding the point you mentioned about the while loop, have you checked how the compiler implements this? It should be possible to get the resulting asm code somehow. Afaik the Arduino thing runs on AVR-GCC, so I suppose you could run the code directly through AVR-GCC with -S switch to get the asm output.

I think your stability issues will be related to your PC's USB port. Many PCs have their USB ports improperly configured and/or use crap controllers, which causes them to deliver unstable/out-of-spec current. Since you say that things are fine when running the board off external power, I'm pretty sure that's what's happening here.

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.

566

(10 replies, posted in Sinclair)

I've actually done some AVR code before, it is indeed a very easy chip to code on. I also have a SeinSmart Uno (Chinese Arduino knock-off) laying around somewhere, and I have an asm programming toolchain installed (Arduino IDE is indeed useless for that), though I can't remember what the actual commands for it were.

In any case, I think Z80 emulation on a 16MHz AVR would be tricky, but possible, albeit not without cutting some corners. I think main challenges will be instruction decoding, and dealing with the AVR's big-endianness. I would suggest:

- Emulation of 4 MHz clock speed instead of 3.5, easier to emulate the correct cycle count like that
- Cut all interrupt-related stuff. This would break SpecialFX and Savage, but I think the benefits far outweigh this. Actual interrupts should be handled outside of the Z80 emulation.
- No R register auto-update.
- No emulation of 5,H,3,N flags and MEMPTR.
- DAA replaced with NOP (would break wtbeep, but oh well)

In any case, I would be willing to work on an AVR Z80 emulation. However, I currently have several other ongoing projects that I want to finish first (MDAL, mainly - made some good progress last month but there's still a few major features missing, such as multi-track sequences, "virtual" sequences, and sample support).

567

(10 replies, posted in Sinclair)

Ok Shiru, you've convinced me of the benefits of a card that run standard beeper engines. Well, maybe Arduino is not such a good idea, after all - using a large Ardunio as the base of this might drive up the costs too much. I mean how much would people be willing to spend on this? 30€? Maybe 50 if it includes a joystick interface?

Either way I know very little about these things, so I'm afraid I can't be of much help.

568

(10 replies, posted in Sinclair)

(discussion split off from the Sleizsa Trio thread)

About a beeper card, would it perhaps make sense to make it Atmega based? I think it might help the popularity of such a device if it could be build from "standard household appliances", eg. Arduino. On the other hand, a Z80-based card could be made in a way that it would run Spectrum beeper engines without adaptation, which would be a big bonus, too. Not sure what's the better approach.

Been a while since I coded something on Fairchild F8... well, here's a new sound routine for the Channel F (aka VES, Grandstand, Saba Videoplay). Sleizsa Trio features 3 tone channels (one of which can play noise instead of tone), globally configurable duty cycles, and 2 interrupting click drums. It uses a mixing algorithm based on Zilogat0r's Squeeker engine for the ZX beeper, which does a somewhat better job with the Channel F's crude sound generator than Sleizsa Duo's pulse interleaving method.

Demo tune: https://soundcloud.com/irrlicht-project … -channel-f
Download: https://github.com/utz82/SleizsaTrio/releases/latest (XM converter included)
Github repo: https://github.com/utz82/SleizsaTrio

Whoa, that's very nicely done. Good find, thanks for sharing!

571

(21 replies, posted in Sinclair)

Yo Zilog, good to read you on here! Your idea about using scalers has actually found it's way into this engine, though I think in a different form than you had envisioned it wink

Anyway, would love to see a new beeper engine from you, too! Squeeker has been very inspiring for me, and in terms of sound it's still one of my all-time favourites.

572

(135 replies, posted in Sinclair)

Been doing some thinking about vibratos. Here's an algo that is reasonably fast, has configurable parameters, and doesn't require a table lookup:

    ld hl,0
    ld de,note_divider
    
    ld c,1                    ;vibrato strength (max 0xf)
    ld b,2                    ;position init (must be ½ of vibrSpeed range - else detune)

loop
    add hl,de        ;11
    ld a,h            ;4
    out (#fe),a        ;11

    ld a,e            ;4
    jr nc,noVibrato        ;12/7

    ret nc            ;5        ;timing
vibrDir                    
    inc b            ;4        ;initial direction (probably needed as configurable parameter)
vibrSpeed equ $+1
    bit 2,b            ;8        ;speed (see above, bit 3 -> ld b,4 | bit 2 -> ld b,2...)
    jp z,vibrDown        ;10
                    
vibrUp
    add a,c            ;4        ;DE += C
    ld e,a            ;4
    adc a,d            ;4
    sub e            ;4
    ld d,a            ;4    
    
    jr loop            ;12
                ;96    

vibrDown
    sub c            ;4        ;DE -= C
    ld e,a            ;4
    sbc a,a            ;4    
    add a,d            ;4            
    ld d,a            ;4    
                    
    jr loop            ;12    
                    
    
noVibrato
    ;... waste some t's
    jr loop            ;12
                ;96

I have a feeling that this thing can be optimized further by using an sbc a,a fallthrough solution, but haven't managed to implement it for the downward slide yet. Let me know if you have any ideas for this.

573

(2 replies, posted in General Discussion)

Belated Happy New Year from me, too! Back from my album recording session now and back on track for 1-bit world domination big_smile

574

(130 replies, posted in Sinclair)

Got a track in the pipes for this. Nothing great, just some simple PhaserX punk rock. Still need to polish it up a bit though.

Finally got around to listening to this properly. Awesome track, love that grinding fx at the end!