Tap2Wav bug

Anything related to the tools Tap2Wav, Tap2CD, Tap2Dsk, Sedoric Disc Manager, Tape Header Creator, WriteDsk, and generaly speaking tools related to the management of Oric data files and devices.
User avatar
waskol
Flight Lieutenant
Posts: 414
Joined: Wed Jun 13, 2007 8:20 pm
Location: FRANCE, Paris

Tap2Wav bug

Post by waskol »

there seems to have a bug in Fabrice's Tap2Wav (which is in the OSDK).

For instance, you cannot convert Xenon1.tap to a wav file. This problem occured with some of my programs made with the OSDK.

I propose there a Tap2Wav I did (for windows :oops: ).
I need to do a command line version for the OSDK :wink:

Extract from tap2wav sources (I think the bug is here : endless loop possible ???) :

Code: Select all

do {
      i=fgetc(in); emit_byte(i);   /* name */
    } while (i!=0);
Here is the new Tap2Wav :
Tap2WavWin.zip

Instructions for real Oric :
1) Create a wav file with a sample rate of 11025 Hz
2) use the windows "tape player" (you can found it here : Start-->Accessories-->entertainment) to play the file, connecting the Jack on the Headphones output of your soundcard or speaker

enjoy !

Edit : utility was updated to v2.0, see in Post n°4 of this thread
Last edited by waskol on Wed Mar 26, 2008 9:52 am, edited 2 times in total.
User avatar
Symoon
Archivist
Posts: 2301
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Re: Tap2Wav bug

Post by Symoon »

I've been working on Fabrice's tape transfer tools this summer, and this bug was on my list :)
I corrected it but I'm waiting for Fabrice to be sure he's OK for a new set of Tape utilites (and I also still have a few things to finish, and I have absolutely no time for this at the moment sadly).

Here's the bug explanation (in French sorry):
Bug corrigé:
Si un fichier TAP n'était pas parfaitement "propre" (contenant par exemple des octets superflus à la fin, cas qui n'est pas exceptionnel), le programme plantait (Windows 98 ) ou générait un fichier WAV sans fin (Windows XP).

Explication:
Le programme commence par "passer" la synchro, puis traite l'en-tête. Dans son traitement de l'en-tête, il lit une série d'octets sans tester la fin de fichier. Il gère notamment le nom du programme par une boucle qui se termine si on rencontre la valeur 0 (qui termine toujours le nom d'un programme). Ensuite on traite le programme Oric lui-même.
Tout ceci boucle, pour le cas des fichiers TAP contenant plusieurs programmes Oric.

Il s'avère que si le fichier TAP ne se termine pas exactement à l'octet près, et contient disons 2 ou 3 octets parasites, Wav2tap va analyser ces octets pour voir s'il s'agit d'un programme. Il ne détecte pas de synchro, et passe directement au traitement de l'en-tête. Si on arrive en fin de fichier sans avoir recontré d'octet contenant la valeur 0, la boucle du nom du programme part en boucle infinie.


More to come in the CEOMag in a few months, once all the work is done :)

Simon
User avatar
waskol
Flight Lieutenant
Posts: 414
Joined: Wed Jun 13, 2007 8:20 pm
Location: FRANCE, Paris

Post by waskol »

OK, then I have pointed out the right thing. We should have :

Code: Select all

   if (feof(in)) break;
   do {
      i=fgetc(in); emit_byte(i);   /* name */
    } while ((i!=0) && (!feof(in)) ;
:wink:

For documentation, this is my source code in Delphi (Pascal), it is pretty much a translation of Fabrice's C++ code kind into Pascal :

Code: Select all

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, Mask, JvExMask, JvToolEdit, ComCtrls;

type TheadArray=ARRAY[0..43]OF BYTE;
 CONST HEADER:TheadArray=(
    $52,$49,$46,$46, $00,$00,$00,$00, $57,$41,$56,$45, $66,$6D,$74,$20,
    $10,$00,$00,$00, $01,$00,$01,$00, $44,$AC,$00,$00, $88,$58,$01,$00,
    $01,$00,$08,$00, $64,$61,$74,$61, $00,$00,$00,$00);
type
  THEAD=packed RECORD
        case b:boolean of
        True:(AsBytes:TheadArray);
        false:(Tag1       : ARRAY[1..4]OF CHAR;  { 00..03  Constante "RIFF"       }
              Size0      : LongWord;             { 04..07  Filesize-8             }
              Tag2       : ARRAY[1..8]OF CHAR; { 08..15  Constante "WAVEfmt..." }
              Size1      : Longword;            {16..19}
              AudioFormat: WORD;                {20..21}
              NumChannels: WORD;                { 22..23  Mono or Stereo         }
              Freq       : LongWord;             { 24..27  Frequence (Hz)         }
              BytePerSec : LongWord;             { 28..31  Freq*NbrByte           }
              NbrByte    : WORD;                { 32..33  (Format div 8)*Mode    }
              Format     : WORD;                { 34..35  8 or 16 bits           }
              Tag3       : ARRAY[1..4]OF CHAR;  { 36..39  Constante "data"       }
              Size2      : LongWord);             { 40..43  Filesize-116           }
        end;

  TForm1 = class(TForm)
    Button1: TButton;
    RadioGroup1: TRadioGroup;
    JvFilenameEdit1: TJvFilenameEdit;
    JvFilenameEdit2: TJvFilenameEdit;
    Label1: TLabel;
    Label2: TLabel;
    ProgressBar1: TProgressBar;
    procedure Button1Click(Sender: TObject);
    procedure JvFilenameEdit1Change(Sender: TObject);
  private
    { Déclarations privées }
    fsout,fsin:TFileStream;
    file_size,speed:integer;
    sample_riff:THEAD;
    ccurrent_level:byte;
    procedure emit_level(size:integer);
    procedure emit_bit(bit:boolean);
    procedure emit_byte(val:byte);
    procedure emit_gap;
    function init:boolean;
  public
    { Déclarations publiques }
  end;

var
  Form1: TForm1;

implementation
 uses MMSystem;
{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var i,size:integer;
    b:byte;
    hheader:array[0..8] of byte;
begin
  speed:=4800;
  sample_riff.AsBytes:=header;
  sample_riff.Size1:=16;
  ccurrent_level:=256-$C0;

if not init then exit;
Cursor:=crHourGlass;
fsin:=TFileStream.Create(JvFilenameEdit1.FileName,fmOpenRead);
ProgressBar1.Max:=fsin.Size;
ProgressBar1.Position:=0;
if FileExists(JvFilenameEdit2.FileName)
then DeleteFile(JvFilenameEdit2.FileName);
fsout:=TFileStream.Create(JvFilenameEdit2.FileName,fmCreate	);

fsout.Write(sample_riff.asbytes,44);
fsin.Position:=0;
while (fsin.Position<fsin.size) do
begin
   b:=$16;
   while (b=$16) do fsin.Read(b,1); // read synchro (0x24 included)

   if (fsin.Position>=fsin.size) then break;
   ProgressBar1.Position:=fsin.Position; Application.ProcessMessages;
   for i:=0 to 255 do emit_byte($16);
   emit_byte($24);
//
    for i:=0 to 8 do
    begin
       fsin.Read(b,1);
       hheader[i]:=b;
       emit_byte(b);  //header
    end;
    ProgressBar1.Position:=fsin.Position; Application.ProcessMessages;

    repeat
      i:=fsin.Read(b,1);
      emit_byte(b);   // name
      ProgressBar1.Position:=fsin.Position; Application.ProcessMessages;
    until ((b=0) or (i=0));

    emit_gap;

    size:=(hheader[4]*256+hheader[5])-(hheader[6]*256+hheader[7])+1;
    for i:=0 to size-1 do begin
                            fsin.Read(b,1);
                            emit_byte(b);
                            ProgressBar1.Position:=fsin.Position; Application.ProcessMessages;
                         end;
end;

   sample_riff.Size2:=fsout.Size;
   sample_riff.Size0:=36+sample_riff.Size2;
   fsout.Seek(0,soFromBeginning);
   fsout.Write(sample_riff.asbytes,44);
 fsin.Free;
 fsout.Free;
 Cursor:=crDefault;
 showmessage('Conversion terminée');
end;

procedure TForm1.emit_bit(bit:boolean);
begin
  case speed of
  4800:begin
          emit_level(1);
          if bit then emit_level(1)
                   else emit_level(2);
       end;
  8000:begin
          if bit then begin
                        emit_level(1);
                        emit_level(2);
                      end
          else begin
                 emit_level(2);
                 emit_level(3);
               end;
        end;
  11025:begin
        if bit then begin
                 emit_level(2);
                 emit_level(2);
               end
          else begin
                 emit_level(3);
                 emit_level(4);
               end;
        end;
    end;
end;

procedure TForm1.emit_byte(val: byte);
var i:byte;
    parity:byte;
begin
  parity:=1;
  emit_bit(false);
  for i:=0 to 7 do
  begin
    parity:=parity+(val and 1);
    emit_bit((val and 1)=1);
    val:=val shr 1;
  end;
  emit_bit((parity and 1)=1);
  emit_bit(true);
  emit_bit(true);
  emit_bit(true);
  emit_bit(true);  // 4 bits stop au lieu de 3.5 pour être sûr que les routines aient du temps
end;

procedure TForm1.emit_gap;
var i:integer;
begin
 //un paquet de bits stop pour laisser le temps d'afficher la ligne de statut
  for i:=0 to 99 do emit_bit(true);
end;

procedure TForm1.emit_level(size: integer);
var i:integer;
begin
   ccurrent_level:=256-ccurrent_level;
   for i:=0 to size-1 do fsout.Write(ccurrent_level,1);
   inc(file_size,size);
end;

function TForm1.init:boolean;
begin
  case RadioGroup1.ItemIndex of
    0:speed:=4800;
    1:speed:=8000;
    2:speed:=11025;
  end;
  sample_riff.freq:=speed;
  sample_riff.NumChannels:=1;
  sample_riff.Format:=8;//8bits
  sample_riff.NbrByte:=sample_riff.NumChannels*(sample_riff.Format div 8);
  sample_riff.BytePerSec:=(speed*sample_riff.NbrByte);


  if not FileExists(JvFilenameEdit1.FileName)
  then begin
         Result:=false;
         exit;
       end;
  if not DirectoryExists(ExtractFilePath(JvFilenameEdit2.FileName))
  then begin
         Result:=false;
         exit;
       end;
  Result:=true;
end;
procedure TForm1.JvFilenameEdit1Change(Sender: TObject);
begin
  JvFilenameEdit2.FileName:=ChangeFileExt(JvFilenameEdit1.FileName,'.wav')
end;

end.

Edit : source code is updated to V2.0, see below
Last edited by waskol on Wed Mar 26, 2008 9:35 am, edited 2 times in total.
User avatar
waskol
Flight Lieutenant
Posts: 414
Joined: Wed Jun 13, 2007 8:20 pm
Location: FRANCE, Paris

Post by waskol »

I have updated my utility :
Tap2WavWin v2.0, converts tap files into wav files
V2.0 fixes minor bugs and adds full compatibility for playing wav files with Windows Media Player, Euphoric and Windows VISTA
for Windows 95,98, NT, 2000, XP, VISTA

Get it here !


By the way, I have updated the source code above.
User avatar
dave3622
Flying Officer
Posts: 242
Joined: Wed Sep 03, 2008 12:13 pm
Location: Brighouse, UK

Re: Tap2Wav bug

Post by dave3622 »

Hi Waskol, Is it possible for you to upload this file again? I am trying to convert several TAP files to WAV but very few of them will load when I connect my Oric to the PC. The games with loading screens show a few graphical errors and the majority simply don't run after the WAV file has ended. The Oric always goes from Searching to Loading but they rarely run. It's driving me insane!!! I've tried many different WAV players and tried all volume levels but to no avail :(
Godzil
Squad Leader
Posts: 774
Joined: Sat May 21, 2011 7:21 pm
Location: Between UK and France
Contact:

Re: Tap2Wav bug

Post by Godzil »

Dave: There could be multiple problem, the first is like for real tape, the volume need to be at a good level, if too high or too low it wont work correctly.

Next if you use the power socket you may have a ground problem between your computer and the Oric. as Oric designer wanted the Oric to have a floating ground by using a 7905 instead of a 7805, when plugin external hardware you need to be carefull, it could also induce some unwanted 50Hz rumble.

If you are using a laptop, try to use it without the power plugged, it may help. I've also encountered some problem with such setup (Computer audio to oric tape input) in really electrically noisy environment, if you can try in another room (yeah it may sounds like black magic)

If you are using a microdisc and run a DOS, please try with the latest version of Sedoric as it seems that some DOS may make the TAPE loading not working.

Also, try to use the tap2cd format, it's error correction is a bit better than what the original tape driver does, it may work better.
User avatar
dave3622
Flying Officer
Posts: 242
Joined: Wed Sep 03, 2008 12:13 pm
Location: Brighouse, UK

Re: Tap2Wav bug

Post by dave3622 »

Thanks for the quick reply Godzil. My computer is Medion all-in-one PC/TV and I think that may be the problem as I never had issues with my old desktop PC. Basically I am trying to restore some of my old games where the tape has degraded preventing the games from loading. The idea is to convert good TAP files to WAV and then transfer them onto new cassettes and then replace the tape in the old cassettes with the new copies. This is a non-starter though due to the WAVS not even loading from the PC. I may have to get my old desktop PC out of the loft and try with that.
User avatar
Symoon
Archivist
Posts: 2301
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Re: Tap2Wav bug

Post by Symoon »

Did you try the classic problem: add some silence at the end of the WAV files.
Many reading programs or devices actually don't read the files entirely, cutting the very end of the sound - the Oric then keeps trying "Loading". This can be easily tested: once the WAV file has ended and the Oric keeps loading, start the file again. If the Oric then ends the loading, it means the last bytes were missing from the reading.
Adding a silence at the end of the WAV file prevents from this boring thing: it's the silence that is cut at the end, not the program.
Godzil
Squad Leader
Posts: 774
Joined: Sat May 21, 2011 7:21 pm
Location: Between UK and France
Contact:

Re: Tap2Wav bug

Post by Godzil »

Symoon wrote:Did you try the classic problem: add some silence at the end of the WAV files.
Many reading programs or devices actually don't read the files entirely, cutting the very end of the sound - the Oric then keeps trying "Loading". This can be easily tested: once the WAV file has ended and the Oric keeps loading, start the file again. If the Oric then ends the loading, it means the last bytes were missing from the reading.
Adding a silence at the end of the WAV file prevents from this boring thing: it's the silence that is cut at the end, not the program.
Yep true, a single missing transition can prevent a complete laoding
User avatar
Dbug
Site Admin
Posts: 4437
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: Tap2Wav bug

Post by Dbug »

I may be a bit retard, but why do not all these tools just add some zeroes at the end of the file they generate?
User avatar
Chema
Game master
Posts: 3013
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:

Re: Tap2Wav bug

Post by Chema »

I am pretty sure that the recompilation of tap2wav I posted somewhere in this forum added a silence at the end.
User avatar
Symoon
Archivist
Posts: 2301
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Re: Tap2Wav bug

Post by Symoon »

Chema wrote:I am pretty sure that the recompilation of tap2wav I posted somewhere in this forum added a silence at the end.
Yes that was an addition I made long ago (2007) hoping then I would be able to finish the slow decoding too. Now this is close to the end, work is taking over again, but still hoping to have some spare time and Fabrice's blessing to officially release all the tools I modified once and for all.
BTW, in 2007 it added a 0.5 seconds silence at the end, but I noticed since then that this was sometimes not enough, so the next release is set at 1.5 seconds.
Post Reply