Пример #1
0
int audiorip_get_track_addresses(int                         fd,
                                 struct track_address* const addresses,
                                 int const                   num_tracks,
                                 int                         verbose)
{
    for (int i = 1; i <= num_tracks; ++i)
    {
        struct cdrom_tocentry current_track = {
            .cdte_track  = i,
            .cdte_format = CDROM_MSF
        };

        if (audiorip_cdrom_read_toc_entry(fd, &current_track) < 0)
        {
            fprintf(stderr, "Failed to read ToC entry for track: %d\n", i);
            audiorip_spindown_and_close(fd);
            return -1;
        }

        /**
         * In order to ascertain the length of the current track, we need
         * to know the address of the next track in the list.  Should the
         * current track be the last one, we simply request the address
         * of the Leadout track.
         */
        struct cdrom_tocentry next_track = {
            .cdte_track  = i == num_tracks ? CDROM_LEADOUT : i + 1,
            .cdte_format = CDROM_MSF
        };

        if (audiorip_cdrom_read_toc_entry(fd, &next_track) < 0)
        {
            if (next_track.cdte_track == CDROM_LEADOUT)
            {
                fprintf(stderr, "Failed to read ToC entry for leadout track\n");
            }
            else
            {
                fprintf(stderr, "Failed to read ToC entry for track: %d\n", i + 1);
            }
            audiorip_spindown_and_close(fd);
            return -1;
        }

        addresses[i - 1].start      = msf_to_frames(current_track.cdte_addr);
        addresses[i - 1].end        = msf_to_frames(next_track.cdte_addr);
        addresses[i - 1].cdrom_addr = current_track.cdte_addr;
        if (verbose)
        {
            fprintf(stdout, "Track %d is %d frames long\n", i, addresses[i - 1].end - addresses[i - 1].start);
        }
    }
    return 0;
}

unsigned char const* audiorip_rip_track(int                        fd,
                                        struct track_address const address,
                                        int                        verbose)
{
    int const      readframes = address.end - address.start;
    unsigned char* buffer     = malloc(readframes * CD_FRAMESIZE_RAW);
    unsigned char  interim_buffer[CD_FRAMES * CD_FRAMESIZE_RAW];

    struct cdrom_read_audio read_audio = {
        .addr        = address.cdrom_addr,
        .addr_format = CDROM_MSF,
        .nframes     = CD_FRAMES,
        .buf         = &interim_buffer[0]
    };

    if (verbose)
    {
        fprintf(stdout, "Reading track from %d to %d\n", address.start, address.end);
    }

    for (int chunk = 0; chunk < readframes; chunk += read_audio.nframes)
    {
        if ((CD_FRAMES + chunk) > readframes)
        {
            read_audio.nframes = readframes - chunk;
        }

        if (audiorip_cdrom_read_audio(fd, &read_audio) < 0)
        {
            fprintf(stderr, "Failed to read chunk\n");
            fprintf(stderr, "%s\n", strerror(errno));
            audiorip_spindown_and_close(fd);
            return NULL;
        }

        memcpy(buffer + (chunk * CD_FRAMESIZE_RAW),
               interim_buffer,
               read_audio.nframes * CD_FRAMESIZE_RAW);

        if (verbose)
        {
            fprintf(stdout, "progress %d/%d\n", chunk, readframes);
        }

        read_audio.addr.msf.frame += read_audio.nframes;
        if (read_audio.addr.msf.frame >= CD_FRAMES)
        {
            read_audio.addr.msf.second += read_audio.addr.msf.frame / CD_FRAMES;
            read_audio.addr.msf.frame = read_audio.addr.msf.frame % CD_FRAMES;
            if (read_audio.addr.msf.second >= 60)
            {
                read_audio.addr.msf.minute += read_audio.addr.msf.second / 60;
                read_audio.addr.msf.second = read_audio.addr.msf.second % 60;
            }
        }
    }

    return buffer;
}

int audiorip_rip_track_to_file(int                        fd,
                               struct track_address const address,
                               char const*                filename,
                               int                        verbose)
{
    FILE* out = fopen(filename, "wb");
    if (strcmp(strrchr(filename, '.'), ".wav") == 0)
    {
        write_wav_header(address, out);
    }
    unsigned char const* track_data = audiorip_rip_track(fd, address, verbose);
    if (track_data == NULL)
    {
        fclose(out);
        return -1;
    }
    fwrite((void const*)track_data,
           (size_t)CD_FRAMESIZE_RAW,
           (size_t)(address.end - address.start),
           out);
    fclose(out);
    audiorip_free_track(track_data);
    return 0;
}
Пример #2
0
chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc *outtoc, chdcd_track_input_info *outinfo)
{
    FILE *infile;
    int i, trknum, cuemode = 0;
    static char token[128];

    if (strstr(tocfname,".gdi"))
    {
        return chdcd_parse_gdi(tocfname, outtoc, outinfo);
    }

    if (strstr(tocfname,".cue"))
    {
        cuemode = 1;
    }

    infile = fopen(tocfname, "rt");

    if (infile == (FILE *)NULL)
    {
        return CHDERR_FILE_NOT_FOUND;
    }

    /* clear structures */
    memset(outtoc, 0, sizeof(cdrom_toc));
    memset(outinfo, 0, sizeof(chdcd_track_input_info));

    trknum = -1;

    while (!feof(infile))
    {
        /* get the next line */
        fgets(linebuffer, 511, infile);

        /* if EOF didn't hit, keep going */
        if (!feof(infile))
        {
            i = 0;

            TOKENIZE

            if ((!strcmp(token, "DATAFILE")) || (!strcmp(token, "AUDIOFILE")) || (!strcmp(token, "FILE")))
            {
                int f;

                /* for bin/cue, this is where you increment the track # */
                if (cuemode)
                {
                    /* make sure we have a size for the current track before moving on */
                    if (trknum > -1)
                    {
                        chdcd_tracksize_helper(trknum, outtoc, outinfo);
                    }
                    trknum++;
                }

                /* found the data file for a track */
                TOKENIZE

                /* keep the filename */
                strncpy(&outinfo->fname[trknum][0], token, strlen(token));

                /* get either the offset or the length */
                TOKENIZE

                if (!strcmp(token, "SWAP"))
                {
                    TOKENIZE

                    outinfo->swap[trknum] = 1;
                }
                else
                {
                    outinfo->swap[trknum] = 0;
                }

                if (token[0] == '#')
                {
                    /* it's a decimal offset, use it */
                    f = strtoul(&token[1], NULL, 10);
                }
                else if (isdigit((UINT8)token[0]))
                {
                    /* convert the time to an offset */
                    f = msf_to_frames( token );

                    f *= (outtoc->tracks[trknum].datasize + outtoc->tracks[trknum].subsize);
                }
                else
                {
                    f = 0;
                }

                outinfo->offset[trknum] = f;

                TOKENIZE

                if (isdigit((UINT8)token[0]))
                {
                    // this could be the length or an offset from the previous field.
                    f = msf_to_frames( token );

                    TOKENIZE

                    if (isdigit((UINT8)token[0]))
                    {
                        // it was an offset.
                        f *= (outtoc->tracks[trknum].datasize + outtoc->tracks[trknum].subsize);

                        outinfo->offset[trknum] += f;

                        // this is the length.
                        f = msf_to_frames( token );
                    }
                }
                else if( trknum == 0 && outinfo->offset[trknum] != 0 )
Пример #3
0
chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc *outtoc, chdcd_track_input_info *outinfo)
{
    FILE *infile;
    int i, trknum;
    static char token[128];

    infile = fopen(tocfname, "rt");

    if (infile == (FILE *)NULL)
    {
        return CHDERR_FILE_NOT_FOUND;
    }

    /* clear structures */
    memset(outtoc, 0, sizeof(cdrom_toc));
    memset(outinfo, 0, sizeof(chdcd_track_input_info));

    trknum = -1;

    while (!feof(infile))
    {
        /* get the next line */
        fgets(linebuffer, 511, infile);

        /* if EOF didn't hit, keep going */
        if (!feof(infile))
        {
            i = 0;

            TOKENIZE

            if ((!strcmp(token, "DATAFILE")) || (!strcmp(token, "AUDIOFILE")) || (!strcmp(token, "FILE")))
            {
                int f;

                /* found the data file for a track */
                TOKENIZE

                /* keep the filename */
                strncpy(&outinfo->fname[trknum][0], token, strlen(token));

                /* get either the offset or the length */
                TOKENIZE

                if (!strcmp(token, "SWAP"))
                {
                    TOKENIZE

                    outinfo->swap[trknum] = 1;
                }
                else
                {
                    outinfo->swap[trknum] = 0;
                }

                if (token[0] == '#')
                {
                    /* it's a decimal offset, use it */
                    f = strtoul(&token[1], NULL, 10);
                }
                else if (isdigit(token[0]))
                {
                    /* convert the time to an offset */
                    f = msf_to_frames( token );

                    f *= (outtoc->tracks[trknum].datasize + outtoc->tracks[trknum].subsize);
                }
                else
                {
                    f = 0;
                }

                outinfo->offset[trknum] = f;

                TOKENIZE

                if (isdigit(token[0]))
                {
                    // this could be the length or an offset from the previous field.
                    f = msf_to_frames( token );

                    TOKENIZE

                    if (isdigit(token[0]))
                    {
                        // it was an offset.
                        f *= (outtoc->tracks[trknum].datasize + outtoc->tracks[trknum].subsize);

                        outinfo->offset[trknum] += f;

                        // this is the length.
                        f = msf_to_frames( token );
                    }
                }
                else if( trknum == 0 && outinfo->offset[trknum] != 0 )
                {
                    /* the 1st track might have a length with no offset */
                    f = outinfo->offset[trknum] / (outtoc->tracks[trknum].datasize + outtoc->tracks[trknum].subsize);
                    outinfo->offset[trknum] = 0;
                }
                else
                {
                    /* guesstimate the track length */
                    UINT64 tlen;
                    printf("Warning: Estimating length of track %d.  If this is not the final or only track\n on the disc, the estimate may be wrong.\n", trknum+1);

                    tlen = get_file_size(outinfo->fname[trknum]) - outinfo->offset[trknum];

                    tlen /= (outtoc->tracks[trknum].datasize + outtoc->tracks[trknum].subsize);

                    f = tlen;
                }

                outtoc->tracks[trknum].frames = f;
            }