Re: 1tracker v0.47
Heh, ignore the updates, keep the brilliant music releases coming. 'Lets Go' is the best!
You are not logged in. Please login or register.
The 1-Bit Forum → Sinclair → 1tracker v0.47
Heh, ignore the updates, keep the brilliant music releases coming. 'Lets Go' is the best!
Thanks! One of reasons why I'm doing updates is to improve my creative throughput, make the process more efficient. I'm also discovering some issues and new ideas as I'm working on more songs. So it is connected, more music releases - more updates to 1tracker, and vice versa.
I also got an idea for another big improvement to the pattern-less system, a link for the already defined named blocks, but I'm still not exactly sure how to implement it interface-wise. It certainly would be a front-end side feature, so no changes needed for the engine scripts. Basically, we already have blocks of variable length and with an optional name. That name can be used as a reference for a 'link' that would synchronize contents of the same-sized same-named blocks. So you would be able to edit one block, and it automatically updates all linked blocks.
I'd need more information on this to make an informed judgement, but generally I think that's a terrain that needs to be treaded very carefully. With automatic updates, there's a risk that you'd accidentally destroy part of your work. Also, 1tracker's current copy/paste-centric approach has the advantage of encouraging variation. When I copy a section and later change some detail in one section, I'll usually apply the changes slightly differently in other copies of that section, often not even deliberately. Happy little accidents, to say it with Bob Ross. For me, it's one of the great strengths of 1tracker. I would possibly be more happy if the updates were manual, that is, you select a source block and one or more target blocks and then issue a command to sync them up.
Generally speaking, I've fully embraced the post-pattern age, haha. My latest pet peeve is actually something else - ticks. And I don't mean the ones that crawl around in the forest trying to kill you with a myriad of diseases. Yeah, those suck, too. Literally. Anyway. Having to deal with ticks aka row length aka speed is annoying. So you start to work on a melody or whatever. Now you want to add some ornaments, so you Ctrl-E that sucker a couple of times. Add yer ornaments, but now you want to save RAM so you optimize the rows. Now all your blocks have odd lengths and it becomes really hard to keep track of where the block borders should be when you move around stuff.
Leaving aside the implications of row transition noise, I think it boils down to this: You always want Speed 1 resolution (especially for 1- and 2-channel engines), but a) you don't want rows with no changes in your output data and b) you don't want all those rows cluttering your tracker view. a) can be solved by having the compiler collapse empty rows, so the big question is how to solve b). I haven't been able to come up with any good solutions yet, it's just something I keep thinking about.
Btw I believe 1tracker's RowOpt feature is wonky. The following:
Sp T
02 C-4
.. ...
.. ...
.. ...
03 D-4
.. ...
.. ...
.. ...
04 E-4
will be optimized to
04 C-4
04 ...
04 D-4
04 ...
04 E-4
which is obviously incorrect.
I was thinking more on the idea with references, and come to the same conclusion, it is better to have it as a manual 'sync' command rather than an automatic update. Besides of the possible unwanted changes, it brings too much trouble handing the insert/delete position (as all data shifts inside all blocks). I'm going to think some more before trying to implement it. At least a simple block copy function is possible and should not hurt anything, like, press something, input an existing block name, and it'll get copied into current position.
I implemented RowOpt to cram down all songs into my 1-bit collection, it worked just fine at the moment, but yes, it may have issues. One thing is that it won't optimize above the slowest speed, which is vary for different engines. I confirm the issue with the example, will look into it.
Alright, here is v0.44:
- A fix for the RowOpt feature to properly handle existing speed changes.
- Reference blocks, block parenting
- Copying/inserting a block by its name
I decided to keep the idea of reference blocks out of the main focus of the project, and implement it in a minimalistic way, just to have it for specific cases, and not make it an integral part of the pattern-less concept. Let's see how useful it actually is.
Trying to get this to work, not sure what I'm doing wrong. I create a block, name it "intro", then move the cursor to a new position, type Ctrl+Q intro, nothing happens.
Btw I think it would be a good idea to move down the help page description for Ctrl-F to where the other block commands are explained. Also, for "copy or insert an existing block by typing in its name", you could omit the "in".
Oh, you probably creating the source block at the very first row. It is a common issue in the code, will fix it ASAP.
Edit: fixed, uploaded.
Thanks! I can confirm it works. Interesting to see this in action, in any case. I'll have to play more with it to see how I'll use it in practise. No time right now but winter is coming...
Edit: Just as I was writing the above, I thought of something. I recently composed a somewhat longer track directly in asm. As I went along, I found myself relying more and more on macros, up to a point where almost the entire track was completely macro-ized. Now, I could definitely imagine using reference blocks in a similar fashion, ie. create a "fake" kick or whatever, give that a name, then improve it later on and use Ctrl-Shift-P to update all the occurances.
However, there are two problems with this. First of all, I've been using a lot of parametric macros as well, eg. for a variable starting pitch on a kick. This could work with the block ref system if a ref update would (optionally) ignore all data in the child blocks that do not match the parent.
The second problem is more serious. Basically, I wouldn't want to create a seperate block for each kick in the track - that would completely defeat the main purpose that blocks currently serve, which is quick navigation and easy copy/pasting of song sections. So basically this would require ref blocks to be a separate thing from the current block sections.
Well, just throwing out some ideas here, obviously nothing really thought out.
Hi Shiru
I use 1-tracker for all my beeper tune compositions these days and find it pretty easy to use now.
Can I request a new feature.
The ability to compile the tune to a specific address ?
All of my phaser 3 tunes have had to be relocated as they've been used in games but I usually have trouble tweaking the .asm to compile with sjasmplus so being able to compile to a user definable address would be great
cheers
Tufty
Spent some time trying to tackle the notorious "Z80Ass error: label already defined!" error again. I still don't know what exactly is going wrong here. The .loop label is indeed set twice under some circumstances (at the start of a block, in any case). So for esex, it will output this:
.song
.loop
db #68,#00,#82,#e4,#82,#e4
.loop
db #01,#01,#01
db #00
dw .loop
Anyway, I found a possible fix. In the affected engines, you usually have something like this near the beginning of the Compile function:
row=startRow;
takeLoop=0;
if(oneShot==1)
{
len=1;
}
else
{
len=songLength-row;
loopRow=-1;
...
Initializing loopRow to -1 before the conditional instead (so it affects both branches) prevents the error from occuring. Not sure if it causes any problems further down the line. I haven't noticed any yet.
Btw it seems the assembler always runs twice. Is this intentional?
Also found the bug that causes peskysoundzx to segfault. It seems that Angelscript does not like implicit type conversions in conditionals. The following changes to peskysoundzx.1te will fix the problem:
line 542:
if(row<int(songLoopStart))//start before loop
line 549:
if(row<int(songLoopEnd))//start inside loop
line 748:
if(takeLoop==1) if(row>=int(songLoopEnd)) row=int(songLoopStart);
Wow. Maybe I'll just rework all the engines and interfaces to avoid the use of uint altogether, so it'll be int all around? I wasn't ever getting any segfaults or crashes under Windows, though.
Oh yeah, loopRow seem to be uninitialized in one of the branches in many engines. Damnit the mindless copy paste of seemingly working framework.
Assembler is intended to be called only once (function ZXStandartExportOptions in zxspectrum.1tl), but the assembler itself is a multi pass, not a single pass one.
I'm pretty sure ZXStandartExportOptions itself is called twice, but I don't know yet where those calls are coming from. While investigating, it turned out my build system is broken and can't link pthreads for some reason. So I need to fix that first.
Just tested it, no, ZXStandartExportOptions is called just once per row or F5 play on my end. To test it quickly, there is Print function, so
void ZXStandartExportOptions(uint format,bool rom)
{
Print("call");
will show each call in the log or the console window (I'm using a debug build with console enabled under Windows).
Yep, I'm using Print, and it's called twice here. Ehhh... well, it's not causing any major issue, so I'd say let's just walk away from this one.
I still can't get rid of suspicion that AngelScript just does not happen to be very stable. Especially between platforms. Too bad it is too late to switch to something, and, well, back then I picked it because it shown very good speed among other script engines, plus it had C-similar syntax. These days Python would be a better bet, I guess, but alas.
I can confirm that your fix made the job, I didn't understand why I had so few engines available, it was because 1tracker crashed when it reached peskysoundzx, then after a second load it didn't try to load the rest of the engines. I've isolated peskysoundzx first, until I've discovered your fix, thanks.
Also found the bug that causes peskysoundzx to segfault.
And thank you Shiru for making new releases of 1tracker, I should try to compose more with it!
A minor update to v0.45. I honestly don't remember all the fixes I did, mostly minor improvements to the engine scripts here and there.
Thanks a lot Shiru
...along with a new song "high and rising". Awesomeo! (SqueekerPlus)
And Shiru's April Earshaver 11-track album included.
Version 0.45 still works on XP. Yah!!!
Another update. Finally, a sample based AY engine! Reverse-engineered the code from Sample Tracker 2.1, and as it works with 48K, it was possible to fit it into the *.AY file container (although I've got ideas on how to go 128K and beyond).
I had to modify Game_Music_Emu in order to make it work, as it didn't fully support simplified AY ports decoding.
The engine also supports Covox, Stereo Covox, and SounDrive, I kept it in Z80 code, but GME does not support these devices, and it seemed to be kinda difficult to add them in, so for now these are not audible in the tracker, but still can be exported as code. This may change in the future.
The engine is already bundled with the tracker. Here is the original ST2.1 reversed code without much modifications, just in case anyone wants to look at it.
Also, extracted a bunch of samples from various TR-DOS disks. They were borrowed from PC software of the time, but they may come handy to re-create the sound of the old digi songs: http://shiru.untergrund.net/temp1/raw_p … om_90s.zip
I can't wait to convert modules from Amiga to 1tracker :-)
Wow, this is a really exciting development.
Thanks Shiru, can't wait to have a go with it
Hi Shiru. Just tried to compile a .tap of the new sampletracker example but it crashes when trying to play back.
The .tap includes a file 40448 bytes in size with a start address of 32768 so I assume this is the issue unless it uses contended memory ?
The 1-Bit Forum → Sinclair → 1tracker v0.47
Powered by PunBB, supported by Informer Technologies, Inc.