Hi
I've saved a very simple BASIC program in a .tap. This loads into FUSE fine. Just for fun I wanted to see what it sounded like.
It converts to a .wav using tape2wav just fine (or appears to, the audio sounds about right though it's been almost 30 years since I last saved / loaded from a speccy using a tape).
However when I try to load the generated wav I get the classic R Tape Loading Error - even when I try normal speed.
Just out of curiosity I also tried converting the .wav back into a .tap, which succeeds but produces a .tap file which won't load either.
I guess it's not really surprising - I assume the audio2tape tool uses the same code as FUSE does to load wavs.
Anyway, in case it's anything that might need looking at I've attached the files I generated, and a copy/paste of the command window output from doing the conversion(s):
C:\AlexRoot\Emulators\Spectrum\FUSE\fuse-utils-1.3.1-win32>tape2wav.exe darbotron.tap darbotron.wav
C:\AlexRoot\Emulators\Spectrum\FUSE\fuse-utils-1.3.1-win32>audio2tape.exe darbotron.wav darbotronNew.tap
Block ended, found 19 bytes
Flag: 0x00
Type: Header
Program: darbotron
First block seconds: 0
Last block seconds: 6.13672
Checksum:PASS Read:0xaf Computed:0xaf
found 1 ROM blocks
C:\AlexRoot\Emulators\Spectrum\FUSE\fuse-utils-1.3.1-win32>
as you can see I didn't do anything fancy, just the vanilla commands.
When you see the basic in the .tap please don't think I'm a looney - I want to make an audio ident for my company which not only sounds like a spectrum loading, but is in fact a runnable basic program and that seemed like a fun / silly think to do with the code...
Thanks for making the emulator BTW it's cool :)
Cheers,
Alex
I can reproduce this problem with fuse 1.5.7, fuse-utils 1.4.3 and libspectrum 1.4.4 creating any simple BASIC program (e.g. 10 PRINT 10) from scratch.
The created .tap file works fine but the .wav created with tape2wav fails.
Ok, so it seems that we have something here.
I saved to tape a minimal BASIC program with a single "10 REM" line. Then I converted it to WAV with Fuse's tape2wav.
I tried to load both files with Fuse (without traps or acceleration). The TAP file loads fine, the WAV file fails. But the WAV file seems correct and I can load it using a different emulator.
I used PlayTZX v0.12c (unrelated to Fuse or libspectrum) to make a new WAV file from the same TAP. I cannot load it with Fuse either.
And here's the interesting thing:
I concatenated two copies of the TAP file (so it would have the same BASIC program twice) and converted it to WAV. Now the first program loads fine but the second fails.
So I suspect that there's an edge missing when libspectrum reaches the end of a WAV file.
I did one last experiment: I took the original WAV created with tape2wav and appended 0xffff to the end. That WAV loads fine now.
I'm attaching a ZIP containing all the files that I used to test this.
Nice work - thanks for looking into this! Much appreciated :)
This fixes the problem with this test case, but I'm not familiar with this routine so please review!
The last patch is incorrect, it works for this test case but the libspectrum_tape_get_next_edge() call returns end-of-block too early with the last edge missing.
I created a TZX file with two consecutive Raw Data blocks and this fails: without any patch because the last part of the first block has the level flag flipped, and it also fails with my previous patch because the last part is missing.
Here's a new patch, with this one I can load all files without errors.
Update 22 Jan: I uploaded the patch again adding a more detailed description and a ChangeLog entry.
Last edit: Alberto Garcia 2019-01-22
While debugging this I noticed something odd. Here's what I get from _get_next_edge() when we go from the first to the second raw data block in the test case that I just appended (raw-data-blocks.zip):
tstates: 873, flags: high
tstates: 873, flags: low
tstates: 873, flags: high
tstates: 873, flags: low
tstates: 1746, flags: high
tstates: 1746, flags: low
tstates: 870, flags: high
tstates: 0, flags: block no-edge
tstates: 1, flags: low
tstates: 3, flags: high
tstates: 873, flags: low
tstates: 873, flags: high
tstates: 873, flags: low
tstates: 873, flags: high
tstates: 873, flags: low
There's a spurious pulse at the beginning of the second block. It's only 1 tstate because that's the bit length stored in the block header, but I suppose that if it was longer it would be able to cause a loading error.
From what I can see it's caused by how raw_data_init() initializes the block state, which I don't quite understand.
Unless I'm missing something, calling libspectrum_tape_raw_data_next_bit() there is guaranteed to make the check at the do...while loop fail, so the end result is that bytes_through_block and bits_through_byte are always set to 0, last_bit is always the negation of the first bit of the new block, and bit_tstates is always bit_length.
That's where the width and the level of that pulse come from.
I reported this problem as [bugs:#444]
Related
Bugs:
#444Sergio, did you try my patch from the 11th of January? That one solves the problem and doesn't have any side effect that I'm aware of.
I think it is rather important because without it Fuse cannot load its own saved tapes.
I don't see any side effect. I'll schedule for next release. I hope Phil or Fred could have a look.
Yes, I'd like to have someone else reviewing it too. I just updated the patch with a longer description and ChangeLog entry.
Thanks Alberto, reviewd and looks great. Committed with an extra regression test added.