Retronitus - Noise from the past!

145679

Comments

  • Well, after all, it is just a lil' beeper speaker. Kind of like some old computers have.

    Regarding the capacitor value, i'm not sure. Maybe 100uF ? With the pretentious audio-grade ones I used, that's the next step up. But 47uF certainly isn't terrible, as you can hear from my recordings.
  • JRetSapDoogJRetSapDoog Posts: 849
    edited 2018-10-31 - 03:11:38
    Maybe my filter is lame. With respect to the left channel in the schematic above, I only use surface mount decoupling caps (104's) for C4 and C5, and I use 180R instead of 750R for R20. Although I think there's a lot of variability on what values can be used, maybe my values and the cap type(s) are not ideal. Then again, it is mono and the speaker is small (though the beeps can be quite loud).
  • Here is the formula to calculate the 3db cutoff frequency
    f3db=1/(2*pi*r1*c1)

    For 19.4KHz the series R is 820 ohms and the capacitor to gnd is 10nF.
  • Maybe my filter is lame. With respect to the left channel in the schematic above, I only use surface mount decoupling caps (104's) for C4 and C5, and I use 180R instead of 750R for R20. Although I think there's a lot of variability on what values can be used, maybe my values and the cap type(s) are not ideal. Then again, it is mono and the speaker is small (though the beeps can be quite loud).
    Your sound circuit works fine for the beeps it was intended for. I was probably silly to try to use it for this music software.

  • JRetSapDoogJRetSapDoog Posts: 849
    edited 2018-11-01 - 02:31:48
    Cluso99: Thanks for the formula. Guess that makes the 3dB cutoff for my current components (180R & 0.1uF) 8.84KHz. Sounds like there's room for improvement.

    David: Well, I had hoped that it would be able to play music, but I never got around to trying any.
  • David: Well, I had hoped that it would be able to play music, but I never got around to trying any.
    That's okay. It plays beeps quite well!

  • Wuerfel_21Wuerfel_21 Posts: 939
    edited 2019-01-13 - 20:22:34
    Hmm, I've been thinking about how to crunch the song data even smaller. Some people think about philosophy and the meaning of life while they're in the shower, I think about PASM....
    The actual note data is already extremely dense, but the pattern sequences are not only quite large, but also aren't very flexible.
    As far as I can tell, at the max tempo, the music routine is called 16 times per step - twice per channel, first to step through the patterns, second to load a new pattern from the sequence. If the max tempo was halved (still plenty fast at 64kHz), there would be four calls per step. There's the one for the pattern, but now we can interpret up to three sequence commands that can be 16 bit each. I haven't tested it yet, but I think replacing patternHandler with this would work:
    patternHandler                                             
    B3            rdbyte    tempValue1, c1_stepPointer       wz
            if_nz jmp       #phaseAcc
                 'nop
    G1            rdword    tempValue1, c1_patternPointer 
    
                  shr       tempValue1, #1                  wc  ' check bit 0
    B4      if_nc mov       c1_stepPointer, tempValue1          ' run pattern
            if_nc jmp       #patternNext
    
                  shr       tempValue1,#1                      wc  ' check bit 1
            if_c  jmp       #patternSetStuff                    ' if set, set instrument, octave, note
                  shr       tempValue1,#1                      wc  ' check bit 2
            if_c  jmp       #patternJump
    '----------------------------------------------------------- 
                  mov       tempo, tempValue1                     
                  shl       tempo, #14                          ' set tempo                      
                  jmp       #patternNext                         
                  
    patternJump
                  shr       tempValue1,#1                      wc ' use bit 3 as sign
                  jmp       #patternSum                                                                
    '-----------------------------------------------------------
    patternSetStuff
    F4            mov       c1_octave, tempValue1                
    F5            shr       c1_octave, #10                       
    E6            mov       c1_note, tempValue1                 ' This takes care of "octave" and "note" init values
    E7            shr       c1_note, #6                          
    E8            and       c1_note, #15              
    '-----------------------------------------------------------                                                             
                  and       tempValue1, #63                     ' Note = noteOn address 
                  add       tempValue1, instrumenPointer              '
    C2            rdlong    c1_noteOn, tempValue1               ' TODO: Why are these longs?
    
    patternNext   mov       tempValue1, #2 wc
    patternSum
    G2            sumc      c1_patternPointer, tempValue1
                  jmp       #phaseAcc
    
    this code is only 3 longs longer than the original code. I will see if I can get it going with one of the existing tunes.

    EDIT: This is slightly shorter, at the cost of using more cycles when not having to load a command.
    Still haven't tested it.
    patternHandler                                             
    B3            rdbyte    tempValue1, c1_stepPointer       wz
            'if_nz jmp      #phaseAcc
                 'nop
    G1      if_z  rdword    tempValue1, c1_patternPointer 
    
             if_z shr       tempValue1, #1                  wc  ' check bit 0
    B4 if_nc_and_z mov      c1_stepPointer, tempValue1          ' run pattern
      if_nc_and_z jmp       #patternNext
    
            if_z  shr       tempValue1,#1                      wc  ' check bit 1
       if_c_and_z jmp       #patternSetStuff                    ' if set, set instrument, octave, note
            if_z  shr       tempValue1,#1                      wc  ' check bit 2
      if_c_or_nz  jmp       #patternJump
    '----------------------------------------------------------- 
                  mov       tempo, tempValue1                     
                  shl       tempo, #14                          ' set tempo                      
                  jmp       #patternNext                         
                  
    patternJump
            if_z  shr       tempValue1,#1                      wc ' use bit 3 as sign
                  jmp       #patternSum                                                                
    '-----------------------------------------------------------
    patternSetStuff
    F4            mov       c1_octave, tempValue1                
    F5            shr       c1_octave, #10                       
    E6            mov       c1_note, tempValue1                 ' This takes care of "octave" and "note" init values
    E7            shr       c1_note, #6                          
    E8            and       c1_note, #15              
    '-----------------------------------------------------------                                                             
                  and       tempValue1, #63                     ' Note = noteOn address 
                  add       tempValue1, instrumenPointer              '
    C2            rdlong    c1_noteOn, tempValue1               ' TODO: Why are these longs?
    
    patternNext   mov       tempValue1, #2 wc
    patternSum
    G2      if_z  sumc      c1_patternPointer, tempValue1
                  jmp       #phaseAcc
    
  • There definitely are ways to improve Retronitus data format and make it more flexible etc. It will be interesting to see what you will come up with. P1 Retronitus is "abandoned" for now, so feel free to pick it apart, improve upon it or change it to suit your needs. I will look in here from time to time when I am not spending time in the P2 forum. In the future I will take what I have learned from Retronitus and make an improved version for the P2.
  • I noticed this while messing around: The square and triangle channels have twice the amplitude of the saw and noise channels. The square channels in particular divide their volume by 8 and then add or subtract that to/from the output, leading to a max. peak-to-peak volume of $1FFFFFFF (whereas to avoid overflow, it should be $0FFFFFFF)
    Is there any particular reason for this?
  • Wuerfel_21Wuerfel_21 Posts: 939
    edited 2019-11-30 - 19:46:41
    So here's another one of those things I've been sitting on for a while: Some Retronitus fork I call Retronitus DX.

    It's all a bit rough around the edges and unfinished and shit, but I'll link it here anyways, because why not.

    - blastershot.rb (get the pun?) can generate customized Retronitus DX cog images. It's super rough, there's no user interface at all, you'll need to manually invoke the gimme_retronitus function through IRB.
    - retrosnd.cpp/retrosnd.hpp are a C++ implementation of Retronitus DX. It's reasonably fast and should(tm) be bit-accurate.
    - retrosnd_env.hpp contains all the definitions one needs to slot the implementation into an environment of choice
    - build_dll.sh will build you a libretronitus.dll library. It should(tm) also work out on non-Windows OSes
    - rsndplay.rb can play a Retronitus DX song given on the command line. (This requires ffmpeg and ffplay to be installed and libretronitus.dll to have been built)
    - Alice.binary is a slightly improved version of that tune (obviously converted to the new data format, too). The source for this can be found here.


    It's been a while, but these are the changes I think I made compared to regular Retronitus:
    - Instrument instruction format changed: Now allows modifying previously internal-only registers (such as the phase accumulator). Jumps have been generalized as a regular register ADD (yes, there can also be absolute jumps now).
    - New 16 bit pattseq format - slightly more compact. I think it's the same as I proposed in this thread before.
    - Probably more, I don't remember.
  • Wuerfel_21Wuerfel_21 Posts: 939
    edited 2020-01-24 - 17:21:22
    Oh, I did some more work recently. First off, it all actually works now! Maybe. I hope.
    (Previously, I committed the wrong versions of some files... oof)
    (EDIT: I did it again! If you looked at the repo in the last 6 minutes, it wasn't updated yet....)

    Also, I did some more muckery:
    - TRG_x now jumps behind the normal instrument entry point. This makes most instruments that use TRG_x one instruction (= 8 bytes) shorter (obviously, this is a breaking change)
    - Tuned notes to 440Hz (hopefully? I can't tell the difference TBH. I just noticed while debugging another issue.)
    - Fixed some bugs in the C++ implementation
    - Source code for Alice.binary is now actually in the repository...

    I've also been working on some more stuff. I've attached some preview thing of an original composition of mine. Well, it's not particularly "original", is it? Not entirely happy with the percussion patches yet.

    (Of course, the forum won't let me upload MP3s. Classic. So I'll treat y'all with a ZIP file containing an MP3 file...)
  • Wuerfel_21Wuerfel_21 Posts: 939
    edited 2020-03-25 - 23:06:53
    Okay, here's some more Retronitus DX stuff:

    Attached to this post, you may find the source code for a couple songs:
    - Alice_main.spin for a slightly updated version of the Alice in Wonderland cover from a while back
    - Fierce_main.spin for the aforementioned original composition, Gipfelarena ~ Fierce battle (oscilloscope visualization coming soon?)
    - Bent_main.spin for another original composition, titled Bent into a neat shape (oscilloscope visualization coming soon?)

    You may also find them in the GitLab repository.

    I've also done some stuff with the tooling. There's now a format for embedding metadata into a Spin file, such as song title, author, comment and channel setup.

    Additionally, I've developed a tool called beepbox2spin that converts the JSON data exported by BeepBox, a beginner friendly browser-based open source sequencer, into a Spin file for Retronitus DX. You still need to do quite a lot of manual editing, but it takes care of the basics well enough.
    What it does:
    - Converts all used patterns
    - Converts pattern sequences (optimizes some (but not all) unnecessary instrument/note set commands)
    - Creates placeholders for all used instruments
    - Arpeggio-type chords (uses lots of memory...)
    - Harmony-type chords
    - Non-"unit" instrument interval settings will duplicate notes onto a second channel (and in case of "fifth" and "octave",shift up the suplicate notes)

    What needs to be done manually:
    - Tempo setting
    - Looping
    - Pitchbends
    - Note-offs
    - Anything instrument-related
    - Anything percussion-related
    - Optimization
    - Everything else

    You may find this tool in the aforementioned GitLab repository.
    BeepBox also possesses a rudimentary MIDI import feature, which may be utilized in a 2-step process to convert MIDI to Retronitus DX.
  • Here we go, got some Oscilloscope videos made:



  • Cool :) More tooling like this can only make it easier for someone with the creativity to get a great Prop-based game going. The ability to play the songs on the host machine is nice, too - don't know how I missed that before? It works well...
    Between your game engine, the others before it, and all the synths that exist there are some great choices for writing a game on the Prop... I wish I had an idea for or the talent for writing one lol. I hope to see yours one day...dunno if it's that Zelda-esque looking one I saw earlier, but it's something to look forward to!

    Cheers
  • Wuerfel_21Wuerfel_21 Posts: 939
    edited 2020-03-26 - 17:33:57
    avsa242 wrote: »
    I hope to see yours one day...dunno if it's that Zelda-esque looking one I saw earlier, but it's something to look forward to!
    Yeah, that is mine.
    I actually recorded some more videos of it that I didn't post here... Altough the last one is already a month old (altough I didn't do much since then. Where did that time go? EDIT: oh, the enemies can actually die now, so I guess that's what I did since then, lol)





    I'm also sitting on an almost-complete VGA version of JET Engine...
  • :open_mouth: that is absolutely stunning looking....jaw on the floor...the chest opening with the item rotating in 3D, as well as the parallaxy horizon are esp. fantastic, but the whole thing looks amazing
  • Uhm, so apparently the songs.zip I posted earlier was lacking the retronitus_header.spin file.

    Here's a new one that also includes a new file, an attempt to do the two-step MIDI conversion thing I was talking about.
  • So I've been working on things again. For one, I've successfully integrated Retronitus DX into The Game(TM) (well, the P1 version. PC version is still TODO, but should be no problem), which required a few changes - SEQ_INIT now has to come before INS_INIT in a song file (this way, the parameters used to initialize Retronitus can stay the same regardless of how many instruments are present) and all channels must have a valid pattern sequence (to simplify init code). All this isn't committed yet, but will be soon(TM), when I'm done with the other thing.

    That other thing being sound effects. To facilitate them, I've developed a new channel type. It implements an LFSR, similar to the noise channel on many soundchips, except you can freely select which bits to tap. By tapping just bit0, you can also play a 32-step 1-bit waveform of your choosing (including a square wave). By tapping bits 17 and 18, you can emulate the NES APU's noise channel. The possibilities are great.

    The implementation looks a bit like this:
    ch8_LFSR
          add c8_phase,c8_freq wc
          muxc :selfmod8,#1
          add  c8_envelope,c8_ASD
          test c8_envelope,volumeBits wz
    if_z  movi c8_envelope,c8_ASD
          max  c8_envelope,c8_vol
    
          test c8_modphase,c8_modspeed wc
    :selfmod8
          rcr c8_modphase,#0-0 wc
          mov  tempValue1,c8_envelope
          shr  tempValue1,#4
          sumc outC,tempValue1
    

    Now the problem is creating sound effects that sound good. I really liked the sound editor in @macca 's GUI tool, but IDK if I have the nerve to deal with setting that up, fixing all the bugs and adapting for DX's slightly different SPU instruction format. So I'll probably have to come up with something significantly less slick.
  • Okay, new Retronitus DX version is live...

    In addition to the changes mentioned above, this introduces some tooling to deal with a new file format called RSX. An RSX file contains up to 255 songs*1 and 254 sound effects*2 in an easy-to-use format. I don't really have a good example for using RSX files, but I have a pretty good description of the format in README.MD. so I guess that's something.


    *1 (each up to 6K, although songs that are not marked as no_sfx will be limited to 5.5K (this is an artifact of how my game dual-purposes the last 512 bytes of the audio buffer. Should probably be optional...))

    *2 (each up to 512 bytes in size, but the first long is reserved for metadata, so 63 instructions will fit)
  • Wuerfel_21Wuerfel_21 Posts: 939
    edited 2020-04-11 - 19:15:13
    New tune!



    Will post source later today, got places to be.

    EDIT: here we go!
  • WOW! That's really impressive :sunglasses:
  • Cluso99 wrote: »
    WOW! That's really impressive :sunglasses:

    Thanks.
  • That was REALLY cool! Just, wow!
  • Here's another simple tune. I've been sitting on this one for ages. Today I opened it up and figured it was basically done. Quickly ported it into Retronitus DX, slapped on an edgy title and uploaded it now...



    Source attached and in the repo as usual
  • Wuerfel,

    I'm interested to know what the difference between this version and the original Retronitus is. Sadly, I don't have the time and energy to find out myself these days. Retronitus is my baby after all, even though I "abandoned" it.
  • Wuerfel_21Wuerfel_21 Posts: 939
    edited 2020-06-08 - 13:54:38
    It's mostly(tm) documented above in this thread. Look there for detail.

    In summary:
    - lots of minor changes
    - Sample rate is 64 kHz
    - Pattern sequence data has a new, slightly more compact 16 bit format
    - Instrument instructions have changed to allow 8 registers to be accessed. The JUMP instruction was axed for this, as the program counter is now just another register (this also means that both absolute and relative jumps can be done).
    - SEQ_INIT comes before INS_INIT
    - The BlasterShot (get the pun?) tool allows auto-generating assembly for custom channel layouts (waveform/panning/amplification of each channel). (In the game I'm writing, Retronitus has to be reloaded from disk whenever the music changes, anyways, so loading a different binary for each tune is easy and allows fun things like having 4 square and 3 tri channels)
    - There is the RSX file format for packing pre-relocated tunes and sound effects alongside their Retronitus binaries. Everything is simple and sector-aligned, so it's really easy to use.
    - There's a C++ version that runs on PC. There's a standalone DLL and player/recorder program (rsndplay.rb, requires ffmpeg/ffplay to be installed and needs some optimization still, as it currently calls into the libretronitus.dll once per sample - starts to crackle if I haven't rebooted my PC for a couple days), but it can also be directly embedded into other programs by providing a custom retrosnd_env.hpp
    - There's a BeepBox2Spin tool that that scaffolds up a Retronitus DX song .spin file from a BeepBox (as of writing, version 3.0.9 has been the latest for a while) JSON song file (the JSONs you see in the repository are the BeepBox files for the tunes). BeepBox itself also has a MIDI import feature, which together with BeepBox2Spin takes care of the bulk of work when converting MIDI to Retronitus DX (songs/Cirno.spin is a result of this process. It's not super well arranged, but the whole tune is there and it took barely an afternoon.).


    And if you or anyone else is interested:
    Quick instructions for messing around with DX with minimal hassle

    Playing a song on a real Propeller:
    - open the *_main.spin file for the song you want
    - change pins and clock if neccessary
    - Load to RAM
    - Profit?

    Playing a song on PC (replace RedSand with the song you want):
    - have Homespun (latest bugfixed version yeti and I made is attached), GCC (for your PC, not PropGCC!), Ruby 2.6+ and FFmpeg/FFplay installed and on PATH
    - clone the repository and open a bash shell in it (installing Git for Windows will install one, if you don't have one already.)
    - run ./build_dll.sh to build libretronitus.dll - there should be no errors
    - run homespun songs/RedSand.spin -b -o songs/RedSand to compile a song into a .binary file
    - run ruby ./rsndplay.rb songs/RedSand.binary to play a binary file (this sometimes doesn't work on the first try - IDK, the whole thing is a bit janky)
    - Profit?

    Creating a song with BeepBox2Spin:
    - create something in BeepBox - the page contains a rough explanation
    (protip: set your preferences like this to enable all the good features:
    bbprefs.png)
    - export to JSON and save in the songs folder
    - run ruby ./beepbox2spin.rb songs/NewSong.json songs/NewSong.spin to generate Spin scaffolding.
    - create a NewSong_main.spin (just copy another one and change the included OBJs) and set it as your main object in PropTool
    .loop
    - run ruby ./blastershot.rb songs/NewSong.spin stereo songs/NewSong_retronitus.spin to generate a Retronitus with the specified channel layout (look at the other songs for how this works). (This is only necessary if you changed the channel layout and want to preview on real Propeller)
    - edit the generated file (an unmodified song will produce no sound, because pattseqs aren't assigned to channels automatically)
    - preview
    - If not yet statisfied, JMP #.loop
    - Share!
    200 x 259 - 14K
  • Wuerfel_21Wuerfel_21 Posts: 939
    edited 2020-06-09 - 14:55:17
    And because I needed to procrastinate had nothing better to do, I made a low-res (256x64), Propeller palette version of the Retronitus logo:

    rsndlogo.png

    Also without the DX letters:
    rsndlogo_nodx.png

    And a bit bigger with non-square pixels (as it would look when displayed through JET Engine):
    rsndlogo_8by7.png

    This could theoretically be displayed in JET Engine, but it'd use up all sprites and I'm not sure if it handles 16 sprites per line without glitches.

    I've also attached the GraphicsGale file with the individual layers - AFAIK only GraphicsGale can open its GAL files, but I hear it works on WINE.
    256 x 64 - 3K
    256 x 64 - 3K
    2048 x 448 - 9K
  • Wuerfel,

    Wow, you have been really busy! To include the PC as a register and extending the instruction range was very clever. The 16 bit pattern sequence format is something I have to have a look at. Interesting indeed!

    Good work!
  • Wuerfel_21Wuerfel_21 Posts: 939
    edited 2020-10-08 - 23:02:19
    Here's another work-in progress thing (ZIPped MP3 as per usual...).

    As you might be able to tell, a cover tune. I'm using it to experiment with instrument design... Gotta love those claps...
  • Tune is done, here's the scope video:

Sign In or Register to comment.