Logicielsmoto.com

Nous sommes le 28 Mar 2024, 17:28

Heures au format UTC + 1 heure




Poster un nouveau sujet Répondre au sujet  [ 3 messages ] 
Auteur Message
 Sujet du message: Conversion K7->WAV pour MO
MessagePosté: 24 Fév 2017, 10:23 
Hors ligne

Inscription: 27 Juin 2006, 19:44
Messages: 1061
Localisation: France (24)
Je reposte ici le programme pour convertir les fichiers MO K7 en fichier WAV présent sur le sujet http://www.logicielsmoto.com/phpBB/viewtopic.php?f=13&t=516, afin de le mettre éventuellement à jour.
Pulkomandy, libre à toi d'y joindre ton programme pour MO6.

Usage: k5towav [--modified] <filename>
--modified : modifie la forme du signal pour essayer de corriger les erreurs de lecture (optionnel)
<filename> : le nom d'un fichier K5. Le fichier WAV sera sauvé dans le même répertoire sous le même nom avec le suffixe ".wav" (16 bits/44100Hz)

Le makefile :
Code:
CC=gcc
CFLAGS= -W -Wall -Werror -O2

all : k5towav


Le programme k5towav :
Code:
/*--------------------------------------------------------*/
/* k5towav (c) Prehisto feb 2015                          */
/* To convert MO K7 file to WAV file                      */
/*--------------------------------------------------------*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#ifndef TRUE
#   define  TRUE 1
#endif
#ifndef FALSE
#   define  FALSE 0
#endif

/* WAV constants */
#define WAVE_HEADER_SIZE  0x2c
#define WAVE_RIFF_CHUNK_SIZE  4
#define WAVE_FORMAT_CHUNK_SIZE  16
#define WAVE_FORMAT_PCM            1
#define WAVE_FORMAT_CHANNELS  1
#define WAVE_FORMAT_SAMPLESPERSEC  44100
#define WAVE_FORMAT_BLOCKALIGN  2
#define WAVE_FORMAT_AVGBYTEPERSEC  WAVE_FORMAT_SAMPLESPERSEC*WAVE_FORMAT_BLOCKALIGN
#define WAVE_FORMAT_BITPERSAMPLE  16

/* Sample parameters */
#define CYCLES_PER_FRAME    19968
#define MICROSEC_PER_FRAME  20000
#define MICROSEC_PER_SEC    1000000
#define CURRENT_VALUE_DEFAULT  0x7fff

static int flag_modified = FALSE;
static int current_value = CURRENT_VALUE_DEFAULT;
static double remain = 0;
static int cycles = 0;



static void write_gap (int length, FILE *file)
{
    int i;

    for (i=0; i<length; i++)
    {
        fputc (current_value&0xff, file );
        fputc ((current_value>>8)&0xff, file );
    }
}



static void write_motoroff (FILE *file)
{
    write_gap (WAVE_FORMAT_SAMPLESPERSEC/2, file);
}



static void write_motoron (FILE *file)
{
    write_gap (WAVE_FORMAT_SAMPLESPERSEC, file);
}



static void write_data_gap (FILE *file)
{
    /* Must have time to do at least :
       4+2   NEXT   LDA    ,X+
       4+2          STA    ,U+
       4+1          LEAY   -1,U
       3            BNE    NEXT
       ... a bit more! */
    write_gap (WAVE_FORMAT_SAMPLESPERSEC/8, file);
}



static void write_signal (FILE *file)
{
    int i;
    double size = ((((double)cycles*(double)MICROSEC_PER_FRAME)
                                   /(double)CYCLES_PER_FRAME)
                                   *(double)WAVE_FORMAT_SAMPLESPERSEC)
                                   /(double)MICROSEC_PER_SEC;
   
    size += remain-(double)((int)remain);
    remain = size;

    /* write signal */
    for (i=0; i<(int)size; i++)
    {
        fputc (current_value&0xff, file );
        fputc ((current_value>>8)&0xff, file );
    }

    /* invert signal */
    current_value=~current_value;

    cycles = 0;
}



static void write_byte_standard (char byte, FILE *file)
{
    int bit;
   
    /* 4     LF1AF  STA    <$2045
       2            LDB    #$08  */
    cycles += 4+2;
    for (bit=0x80; bit>0; bit>>=1)
    {
        /* 7     LF1B3  BSR    LF1CB
           2     LF1CB  LDA    #$40
           4+0          EORA    ,U
           4+0          STA     ,U  */
        cycles += 7+2+4+4;
        write_signal (file);
        /* 5            RTS
           3            LDX    #$002D
           7            BSR    LF1A2
           4+1   LF1A2  LEAX   -$01,X
           3            BNE    LF1A2
           2            CLRA
           5            RTS
           3            LDX    #$0032
           6            ASL    <$2045
           3            BCC    LF1C5  */
        cycles += 5+3+7+(0x2d*(4+1+3))+2+5+3+6+3;

        if (((int)byte & bit) == 0)
        {
            /* 7     LF1C5  BSR    LF1A2
               4+1   LF1A2  LEAX   -$01,X
               3            BNE    LF1A2
               2            CLRA
               5            RTS       */
            cycles += 7+(0x32*(4+1+3))+2+5;
        }
        else
        {
            /* 7            BSR    LF1CB
               2     LF1CB  LDA    #$40
               4+0          EORA   ,U
               4+0          STA    ,U   */
            cycles += 7+2+4+4;
            write_signal (file);
            /* 5            RTS
               4+1          LEAX   -$03,X
               7     LF1C5  BSR    LF1A2
               4+1   LF1A2  LEAX   -$01,X
               3            BNE    LF1A2
               2            CLRA
               5            RTS    */
            cycles += 5+4+1+7+((0x32-3)*(4+1+3))+2+5;
        }
        /* 2            DECB
           3            BNE    LF1B3  */
        cycles += 5;
    }
    /* 5            RTS   */
    cycles += 5;
}



static void write_byte_modified (char byte, FILE *file)
{
    int bit;
   
    /* 4     LF1AF  STA    <$2045
       2            LDB    #$08  */
    cycles += 4+2;
    for (bit=0x80; bit>0; bit>>=1)
    {
        /* 7     LF1B3  BSR    LF1CB
           2     LF1CB  LDA    #$40
           4+0          EORA    ,U
           4+0          STA     ,U  */
        cycles += 7+2+4+4;
        write_signal (file);
        cycles += 269;

        if (((int)byte & bit) == 1)
        {
            write_signal (file);
        }
        cycles += 564;

        /* 2            DECB
           3            BNE    LF1B3  */
        cycles += 5;
    }
    /* 5            RTS   */
    cycles += 5;
}



static void write_byte (char byte, FILE *file)
{
    if (flag_modified == FALSE)
        write_byte_standard (byte, file);
    else
        write_byte_modified (byte, file);
}



#define STOCK_LENGTH  40
#define MOTOR_STOPS_AFTER_THIS_BLOCK 0x01
#define MOTOR_STOPS_AFTER_DATA_BLOCK 0x02

static void convert_file (FILE *bin_file, FILE *wav_file)
{
    static char stock[STOCK_LENGTH];
    static size_t length = 0;
    static size_t size = 0;
    static int motor_status = 0;
    char dcmoto_mark1[] = "DCMOTO\1\1\1\1\1\1\1\1\1\1\x3c\x5a";
    char dcmoto_mark2[] = "\xdc\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\x3c\x5a";
    char basic_mark[]   = "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\x3c\x5a";

    do
    {
        if ((length < STOCK_LENGTH) && (feof (bin_file) == 0))
        {
            size = fread(stock+length, 1, STOCK_LENGTH-length, bin_file);
            length += size;
        }

        if (length > 19)
        {
            if ((memcmp (dcmoto_mark1, stock, 18) == 0)
             || (memcmp (dcmoto_mark2, stock, 18) == 0)
             || (memcmp (basic_mark, stock, 18) == 0))
            {
                if (motor_status != 0)
                {
                    write_motoroff (wav_file);
                    motor_status &= ~MOTOR_STOPS_AFTER_THIS_BLOCK;
                }
                memset (stock, 0x01, 6);

                cycles = 0;
                remain = 0;

                if (stock[18] == '\0')
                {
                    write_motoron (wav_file);
                    motor_status &= ~MOTOR_STOPS_AFTER_DATA_BLOCK;
                    if ((length > (18+2+0x0d)) && (stock[18+2+0x0d] != '\0'))
                    {
                        motor_status |= MOTOR_STOPS_AFTER_DATA_BLOCK;
                    }
                    motor_status |= MOTOR_STOPS_AFTER_THIS_BLOCK;
                }
                else
                {
                    if ((motor_status & MOTOR_STOPS_AFTER_DATA_BLOCK) != 0)
                    {
                        write_motoron (wav_file);
                    }
                    else
                    {
                        write_data_gap (wav_file);
                    }

                    if (stock[18] == '\xff')
                    {
                        motor_status &= ~MOTOR_STOPS_AFTER_DATA_BLOCK;
                        motor_status |= MOTOR_STOPS_AFTER_THIS_BLOCK;
                    }
                    else
                    {
                        motor_status &= ~MOTOR_STOPS_AFTER_THIS_BLOCK;
                    }
                }
            }
        }
        cycles += 4+2+7;  /* For preparing data to be written */
        write_byte (*stock, wav_file);
        cycles += 6+3;    /* For the loop */

        memmove (stock, stock+1, STOCK_LENGTH-1);
        length--;
    } while (length > 0);
}



static void write_le4 (int value, FILE *file)
{
    fputc( value&0xff, file );
    fputc( (value>>8)&0xff, file );
    fputc( (value>>16)&0xff, file );
    fputc( (value>>24)&0xff, file );
}



static void write_le2 (int value, FILE *file)
{
    fputc( value&0xff, file );
    fputc( (value>>8)&0xff, file );
}



static void write_id (char *id, FILE *file)
{
    int size = fwrite (id, 1, 4, file);
    (void)size;
}



static void update_wav_header (char *filename)
{
    FILE *file;
    struct stat st;

    stat( filename, &st );

    file = fopen (filename, "rb+");
    if (file != NULL)
    {
        write_id  ("RIFF", file);
        write_le4 ((int)st.st_size-WAVE_RIFF_CHUNK_SIZE, file);
        write_id  ("WAVE", file);
        write_id  ("fmt ", file);
        write_le4 (WAVE_FORMAT_CHUNK_SIZE, file);
        write_le2 (WAVE_FORMAT_PCM, file);
        write_le2 (WAVE_FORMAT_CHANNELS, file);
        write_le4 (WAVE_FORMAT_SAMPLESPERSEC, file);
        write_le4 (WAVE_FORMAT_AVGBYTEPERSEC, file);
        write_le2 (WAVE_FORMAT_BLOCKALIGN, file);
        write_le2 (WAVE_FORMAT_BITPERSAMPLE, file);
        write_id  ("data", file);
        write_le4 ((int)st.st_size-WAVE_HEADER_SIZE, file);
        fclose (file);
    }
}



static void write_wav (char *bin_name, char *wav_name)
{
    int i;
    FILE *bin_file;
    FILE *wav_file;

    bin_file = fopen (bin_name, "rb");
    if (bin_file != NULL)
    {
        wav_file = fopen (wav_name, "wb");
        if (wav_file != NULL)
        {
            /* Create WAV header gap */
            for (i=0; i<WAVE_HEADER_SIZE; i++)
            {
                fputc (0x00, wav_file);
            }

            /* Write WAV data */
            write_motoron (wav_file);
            convert_file (bin_file, wav_file);
            write_motoroff (wav_file);
            fclose (wav_file);
            update_wav_header (wav_name);
        }
        else
        {
            printf ("*** Can not write file %s\n", wav_name);
        }
        fclose (bin_file);
    }
    else
    {
        printf ("*** Can not read file %s\n", bin_name);
    }
}



static int info (void)
{
    printf ("k5towav (c) Prehisto feb 2015\n");
    printf ("     Usage : k5towav [--modified] <filename>\n");
    return EXIT_FAILURE;
}



int main (int argc, char *argv[])
{
    int i;
    char bin_name[300] = "";
    char wav_name[300] = "";

    for (i=1; i<argc; i++)
    {
        if (argv[i][0] == '-')
        {
            if (strcmp (argv[i], "--modified") == 0)
            {
                flag_modified = TRUE;
            }
            else
            {
                printf ("*** option '%s' unknown\n", argv[i]);
                return info ();
            }
        }   
        else
        {
            if (*bin_name == '\0')
            {
                strcpy(bin_name, argv[i]);
            }
            else
            {
                return info ();
            }
        }
    }

    sprintf (wav_name, "%s.wav", bin_name);

    write_wav (bin_name, wav_name);

    return EXIT_SUCCESS;
}


EDIT 20 fév 2015 15:56 : Le programme reconnaît maintenant quelques repères DCMOTO. Mais, à part corriger les bugs, je n'irai pas plus loin. Ce programme est juste un exemple.
EDIT 20 fév 2015 19:47 : Correction de bug. MICROSEC_PER_FRAME était incrémenté par 10 pour le calcul de 'size' dans write_signal() , ce qui était inutile. Juste un reste de test.
EDIT 21 fév 2015 21:51 : Simplification du code.
EDIT 21 fév 2015 22:53 : Correction d'offset, d'une condition et de la compilation.
EDIT 22 fév 2015 18:27 : Simplification du code.

_________________
Marche a suivre pour s'inscrire sur ce forum
Do not forget to contact one of the administrators to validate your registration.
Le site des démos de Puls
L'émulateur Teo


Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: Conversion K7->WAV pour MO
MessagePosté: 24 Fév 2017, 19:48 
Hors ligne

Inscription: 24 Juil 2010, 16:08
Messages: 454
Localisation: France
Ma version n'a pas bougé: http://pulkomandy.tk/projects/thomson/b ... /k5towav.c

Pour rappel, les modifications que j'avais éffectuées:
- Passage de 44.100kHz a 11.025kHz pour réduire la taille des fichiers
- Doublage de la vitesse pour écrire dans le format du MO6 (2 fois plus rapide que le MO5)
- Reconaissance de "DCMO6" dans l'en-tête des fichiers (marquage ajouté sur certains fichiers de dcmoto.free.fr)
- Augmentation du délai pour un "motor off", car ma configuration ne permet pas de détecter l'arrêt du moteur du lecteur de cassettes.


Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: Conversion K7->WAV pour MO
MessagePosté: 26 Fév 2017, 15:00 
Hors ligne

Inscription: 21 Avr 2010, 10:59
Messages: 253
avec cette méthode pas mal de fichiers .K7 ne vont pas marcher (et historiquement c'est de ma faute).
Les premières K7 MO5 converties avec le cable LEP vers port série ne sont pas alignées sur un octet, pour la synchro on retrouve donc soit 010101 soit autrechose comme 020202 etc... on peut aussi retrouver des erreurs de synchro plus ou moins volontaires... (cette méthode permet de charger correctement pulsar II dans les toutes premières versions de mon emu MO5 en activant le mode "real K7'). l'émulateur fonctionne avec parceque c'est le routine de lecture d'un bit qui a été patché en ROM et pas la routine pour un octet.

http://www.alternative-system.com/speci ... sfert.html

Pour ces fichiers là il faudrait d'abord les reconvertir avec un outil pour recaler sur les octets... j'ai ca dans un coin...

_________________
http://www.alternative-system.com


Haut
 Profil  
Répondre en citant le message  
Afficher les messages postés depuis:  Trier par  
Poster un nouveau sujet Répondre au sujet  [ 3 messages ] 

Heures au format UTC + 1 heure


Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 37 invités


Vous ne pouvez pas poster de nouveaux sujets
Vous ne pouvez pas répondre aux sujets
Vous ne pouvez pas éditer vos messages
Vous ne pouvez pas supprimer vos messages
Vous ne pouvez pas joindre des fichiers

Rechercher:
Aller à:  
cron
Développé par phpBB® Forum Software © phpBB Group
Traduction par phpBB-fr.com