Hi there,
I'm working on a tool called TAP2F16 for ".TAP to Fast *1.6 speed". The tool produces a 44kHz WAV file that, you guessed it, runs around 1,6 times faster than original tapes. That means for instance that a program loading in 5mins will now load in 3mins.

You may wonder "why?", since TAP2CD already does a similar job much, much faster?
Well, TAP2F16 has the advantage of loading on standard Orics, without any loader, or ROM modification. So it should work on Atmos and Oric-1 as well, and maybe (no guarantee) load some programs that didn't work with TAP2CD (Lone Raider for instance).

But so far I only could test it on Atmos (ROM 1.1). Could anyone help and make a test on a real Oric-1? You can find attached a ZIP with Lone Raider.
Of course you can also test it on your Atmos to confirm it's working - or not. As I'm really playing with the limits of the ROM decoding routines, any test is welcome.

This tool, based on Fabrice's TAP2WAV, converts Oric .TAP files to 44kHz (big) WAV files designed to work on any standard Oric, but that will load about 1.6 times faster than the usual FAST speed - "F16" standing for "Fast *1.6".
One may wonder "why?", since TAP2CD from Fabrice already loads programs much, much faster. Well here the challenge was: what can be achieved with zero hadware or software change? So a few more programs work, and it also works on Oric-1's ROM 1.0. No impressive upgrade but funny to see that digital player reliability allows an average 38% improvement.

THE IDEA
So you got it: no special routines here, just an optimized tape signal. It was based on a study of the ROMs.
The standard signal, in FAST, codes a bit "1" by a 416 microseconds sinusoid (2 x a 208µs duration), and a "0" by a 624µs sinusoid (3 x 208µs). When reading a tape, the VIA 6522 detects a sinusoid, then sends a flag to the Oric, which will start counting the time between it and the next one (and so on).
Then Oric compares this duration to 512µs (which is the middle between 416 and 624µs), and stores a "0" bit for a longer duration, or a "1" for a shorter duration. So there is an 20% margin which was useful with 1980's tape players running at different speeds.

This decoding method is interesting with nowadays digital players, which offer good audio quality and perfect reading speed. So let's try and save loading time on two sides:
1- the 20% margin is now useless
2- the "1" bit has no minimal length! So it can be much shorter... Its only limits are harware response and ROM decoding time.

After painful counting of ASM instructions duration, confirmed by testing with a small program, the results show that the minimal duration for a "0" is 529µs (at 44kHz, which is 23 samples), and 115µs for a "1" (5 samples). Try to remove ONE sample to any of these values, and the Oric won't load anymore.

So you can see right now that you'll need a PERFECT WAV player, without any audio interference - a single sample not read and it's over. For instance, on my PC, I need to shut down WiFi, and even to reboot it from time to time - seems after a while it's not able (or doesn't have enough ressources anymore) to read WAV files perfectly.

This has been successfully tested on Atmos and Oric-1, even the display of the program name, or the making of a whole byte is OK, the Oric still has time to compute them even if the stop bits are shorter (and BTW, I set 3 stop bits, instead of 4 with TAP2WAV, to save a little more time).

THE PROGRAM
You should find TAP2F16.EXE compiled in two versions: 16 and 32 bits, as well as the source code in TAP2F16.C. 16 bits if for older machines still running real MS-DOS, 32 bits should run on recent computers (even 64 bits)

Just type: TAP2F16 yourprogram.TAP wavfilename.WAV

In case of failure, I have added a "-o" ("old machine") switch which adds an extra sample (so 23µs) to each "0" and "1" bit. I'm not sure it's really useful, but it may help if your Oric fails to load (or if the comptuer fails playing the WAV file properly!), at the price of a longer loading time...

Symoon, thank you for the tool!
Nice idea and implementation and very informative explanation.
I can confirm, that Tap2F16 works under Linux 32/64 too.
There are 3-4 harmless warnings during compilation, but that's no problem at all.

iss wrote:There are 3-4 harmless warnings during compilation, but that's no problem at all.

Thanks for the feedback
Warnings are very likely with me, I'm a crappy C programmer (only learnt it in 1998 and never really used it since then).
I wouldn't have been able to do anything if Fabrice didn't code his tools in the 1st place

Symoon wrote:THE IDEA
So you got it: no special routines here, just an optimized tape signal. It was based on a study of the ROMs.
The standard signal, in FAST, codes a bit "1" by a 416 microseconds sinusoid (2 x a 208µs duration), and a "0" by a 624µs sinusoid (3 x 208µs). When reading a tape, the VIA 6522 detects a sinusoid, then sends a flag to the Oric, which will start counting the time between it and the next one (and so on).
Then Oric compares this duration to 512µs (which is the middle between 416 and 624µs), and stores a "0" bit for a longer duration, or a "1" for a shorter duration. So there is an 20% margin which was useful with 1980's tape players running at different speeds.

Apologies; possibly this is a bit of a derailment but it's pretty clear you're on top of this stuff so is it okay to ask a quick couple of questions about the ROM routines for tape reading?

per Hardware programming on the Oric in fast mode the wave produced for a '1' is a 208µs segment plus another 208µs segment, and the wave produced for a '0' is a 208µs segment followed by a 416µs segment. From what you're saying it sounds like all the ROM measures is the sum of the two? It would be equally happy, even with a real speed-variable tape, if the '1' were two 312µs segments?

is the ROM deliberately or impliedly sensitive to phase? E.g. is it always summing one low then one high (or vice versa), or merely taking the time between each transition and tracking the rest of a byte from the first thing that looks like a 0 through until it's got the parity bit?

ThomH wrote:per Hardware programming on the Oric in fast mode the wave produced for a '1' is a 208µs segment plus another 208µs segment, and the wave produced for a '0' is a 208µs segment followed by a 416µs segment. From what you're saying it sounds like all the ROM measures is the sum of the two? It would be equally happy, even with a real speed-variable tape, if the '1' were two 312µs segments?

Two 312µs segments would probably give a '0'. Those segments are a convenient way to describe/generate the signal, but they're not used to decode it.
From (my bad) memory here's how it works:
- the 6522 detects a positive transition
- then its 16-bits timer begins to decrease, starting from #FFFF (in µs)
- another positive transition is detected by the 6522
- then the Oric ROM saves and checks the higer timer byte value: if it's lower than #FE then it's a '0' (time has decreased more than twice 256µs), if it's equal or higher (#FExx or #FFxx) then it's a '1' (time has decreased less that twice 256µs)
The only important things about the signal are:
1- it has to be done so the 6522 detects positive transitions
2- it has to let the right amount of time pass between those transitions

ThomH wrote:is the ROM deliberately or impliedly sensitive to phase? E.g. is it always summing one low then one high (or vice versa), or merely taking the time between each transition and tracking the rest of a byte from the first thing that looks like a 0 through until it's got the parity bit?

So it's based on time. Starts decoding a byte (+parity) with a '0' start bit, and loops on stop bits ('1') waiting for the next start bit.

Thanks! That's helped a lot. Of the platforms I happen already to know about, that's actually really close to the way the Vic-20 does it: on that platform a 1-bit version of the input wave is connected to a VIA control line to catch transitions in one direction only, counted against that VIA's second counter; the implementation then diverges only because Commodore's code waits for an interrupt either way: if it was the timer interrupt then that's a long wave, if it was the control line input then it's a short.

Symoon, I want to confirm (one year later ) the minimal duration for a "0" is 529µs and for a "1" - 115µs.
Currently I'm using successfully T0=541µs and T1=125µs and the loading is very reliable even with WiFi turned on .
Unfortunately, strange problem occurs at first 3-4 bytes of the read data - I mean exactly the data (!) - the header is loaded OK, the name of the program is displayed OK, the start and end address are OK, but not the first bytes.
Do you have ever experienced such error?
I hope to fix this issue and there will be surprise (or two) for all .

Interesting
The thing is that, after the header is loaded, there are several operations done by the Oric: displaying the program names, and so on.
This requires time, and IIRC when saving there are more than 3 stop-bits sent right after the end of the header (from memory, it's 4 or 6 stop bits, but check it again please!).

So if there aren't enough stop-bits in the signal (after the header) to give time to process the name display, the following bytes are affected when loading back the program. As the stop bits are "1" and their time is shortened a lot with F16, maybe that's the problem.
Tap2F16.c (just like Tap2wav) builds the WAV file with MANY MORE stop-bits than the ROM after the header: 100 instead of the "4-or-6-I-can't-recall", so there's plenty of time.

I wonder if this, plus the fact that your duration values are different from mine, is not giving a hint on what your surprise could be :-p

EDIT: found back what I had checked: with Euprhoric, ROM 1.1, fast AND slow speed: 6 stop bits instead of 3 after the program's name. Though I trust Euphoric, it would be safe to confirm with a real machine (or a ROM instructions analysis), and with ROM 1.0 too as routines were modified between 1.0 and 1.1.

I missed this during the fight with other serious issues. I'll check tonight and will report back the result.
Else, yes, my timings are really hint - they are based on 48000 sampling rate which is the native playback sampling rate on many hardware platforms, for instance android ....