📄 sbpcd
字号:
Once activated, it does not stop before success or end-of-list. This may beuseful within "universal" CDROM installation boot floppies (but using the loadable module would be better because it allows an "extended" auto-probingwithout fearing NE2000 cards).To shorten the auto-probing list to a single entry, set DISTRIBUTION 0 withinsbpcd.h.Setting up address and interface type:--------------------------------------If your I/O port address is not 0x340, you have to look for the #defines nearthe beginning of sbpcd.h and configure them: set SBPRO to 0 or 1 or 2, andchange CDROM_PORT to the address of your CDROM I/O port.Almost all of the "SoundBlaster compatible" cards behave like the no-soundinterfaces, i.e. need SBPRO 0! With "original" SB Pro cards, an initial setting of CD_volume through thesound card's MIXER register gets done.If you are using a "compatible" sound card of types "LaserMate" or "SPEA",you can set SOUND_BASE (in sbpcd.h) to get it done with your card, too...Using audio CDs:----------------Workman, WorkBone, xcdplayer, cdplayer and the nice little tool "cdplay" (seeREADME.aztcd from the Aztech driver package) should work.The program CDplayer likes to talk to "/dev/mcd" only, xcdplayer wants"/dev/rsr0", workman loves "/dev/sr0" or "/dev/cdrom" - so, make the appropriate links to use them without the need to supply parameters.Copying audio tracks:---------------------The following program will copy track 1 (or a piece of it) from an audio CDinto the file "track01":/*=================== begin program ========================================*//* * read an audio track from a CD * * (c) 1994 Eberhard Moenkeberg <emoenke@gwdg.de> * may be used & enhanced freely * * Due to non-existent sync bytes at the beginning of each audio frame (or due * to a firmware bug within all known drives?), it is currently a kind of * fortune if two consecutive frames fit together. * Usually, they overlap, or a little piece is missing. This happens in units * of 24-byte chunks. It has to get fixed by higher-level software (reading * until an overlap occurs, and then eliminate the overlapping chunks). * ftp.gwdg.de:/pub/linux/misc/cdda2wav-sbpcd.*.tar.gz holds an example of * such an algorithm. * This example program further is missing to obtain the SubChannel data * which belong to each frame. * * This is only an example of the low-level access routine. The read data are * pure 16-bit CDDA values; they have to get converted to make sound out of * them. * It is no fun to listen to it without prior overlap/underlap correction! */#include <stdio.h>#include <sys/ioctl.h>#include <linux/cdrom.h>static struct cdrom_tochdr hdr;static struct cdrom_tocentry entry[101];static struct cdrom_read_audio arg;static u_char buffer[CD_FRAMESIZE_RAW];static int datafile, drive;static int i, j, limit, track, err;static char filename[32];main(int argc, char *argv[]){/* * open /dev/cdrom */ drive=open("/dev/cdrom", 0); if (drive<0) { fprintf(stderr, "can't open drive.\n"); exit (-1); }/* * get TocHeader */ fprintf(stdout, "getting TocHeader...\n"); err=ioctl(drive, CDROMREADTOCHDR, &hdr); if (err!=0) { fprintf(stderr, "can't get TocHeader (error %d).\n", err); exit (-1); } else fprintf(stdout, "TocHeader: %d %d\n", hdr.cdth_trk0, hdr.cdth_trk1);/* * get and display all TocEntries */ fprintf(stdout, "getting TocEntries...\n"); for (i=1;i<=hdr.cdth_trk1+1;i++) { if (i!=hdr.cdth_trk1+1) entry[i].cdte_track = i; else entry[i].cdte_track = CDROM_LEADOUT; entry[i].cdte_format = CDROM_LBA; err=ioctl(drive, CDROMREADTOCENTRY, &entry[i]); if (err!=0) { fprintf(stderr, "can't get TocEntry #%d (error %d).\n", i, err); exit (-1); } else { fprintf(stdout, "TocEntry #%d: %1X %1X %06X %02X\n", entry[i].cdte_track, entry[i].cdte_adr, entry[i].cdte_ctrl, entry[i].cdte_addr.lba, entry[i].cdte_datamode); } } fprintf(stdout, "got all TocEntries.\n");/* * ask for track number (not implemented here) */track=1;#if 0 /* just read a little piece (4 seconds) */entry[track+1].cdte_addr.lba=entry[track].cdte_addr.lba+300;#endif/* * read track into file */ sprintf(filename, "track%02d\0", track); datafile=creat(filename, 0755); if (datafile<0) { fprintf(stderr, "can't open datafile %s.\n", filename); exit (-1); } arg.addr.lba=entry[track].cdte_addr.lba; arg.addr_format=CDROM_LBA; /* CDROM_MSF would be possible here, too. */ arg.nframes=1; arg.buf=&buffer[0]; limit=entry[track+1].cdte_addr.lba; for (;arg.addr.lba<limit;arg.addr.lba++) { err=ioctl(drive, CDROMREADAUDIO, &arg); if (err!=0) { fprintf(stderr, "can't read abs. frame #%d (error %d).\n", arg.addr.lba, err); } j=write(datafile, &buffer[0], CD_FRAMESIZE_RAW); if (j!=CD_FRAMESIZE_RAW) { fprintf(stderr,"I/O error (datafile) at rel. frame %d\n", arg.addr.lba-entry[track].cdte_addr.lba); } arg.addr.lba++; }}/*===================== end program ========================================*/At ftp.gwdg.de:/pub/linux/misc/cdda2wav-sbpcd.*.tar.gz is an adapted version ofHeiko Eissfeldt's digital-audio to .WAV converter (the original is there, too).This is preliminary, as Heiko himself will care about it.Known problems:---------------Currently, the detection of disk change or removal is actively disabled.Most attempts to read the UPC/EAN code result in a stream of zeroes. All mydrives are mostly telling there is no UPC/EAN code on disk or there is, but itis an all-zero number. I guess now almost no CD holds such a number.Bug reports, comments, wishes, donations (technical information is a donation,too :-) etc. to emoenke@gwdg.de.SnailMail address, preferable for CD editors if they want to submit a free"cooperation" copy: Eberhard Moenkeberg Reinholdstr. 14 D-37083 Goettingen Germany---Appendix -- the "cdtester" utility:/* * cdtester.c -- test the audio functions of a CD driver * * (c) 1995 Eberhard Moenkeberg <emoenke@gwdg.de> * published under the GPL * * made under heavy use of the "Tiny Audio CD Player" * from Werner Zimmermann <zimmerma@rz.fht-esslingen.de> * (see linux/drivers/block/README.aztcd) */#undef AZT_PRIVATE_IOCTLS /* not supported by every CDROM driver */#define SBP_PRIVATE_IOCTLS /* not supported by every CDROM driver */#include <stdio.h>#include <stdio.h>#include <malloc.h>#include <sys/ioctl.h>#include <linux/cdrom.h>#ifdef AZT_PRIVATE_IOCTLS#include <linux/../../drivers/cdrom/aztcd.h>#endif AZT_PRIVATE_IOCTLS#ifdef SBP_PRIVATE_IOCTLS#include <linux/../../drivers/cdrom/sbpcd.h>#include <linux/fs.h>#endif SBP_PRIVATE_IOCTLSstruct cdrom_tochdr hdr;struct cdrom_tochdr tocHdr;struct cdrom_tocentry TocEntry[101];struct cdrom_tocentry entry;struct cdrom_multisession ms_info;struct cdrom_read_audio read_audio;struct cdrom_ti ti;struct cdrom_subchnl subchnl;struct cdrom_msf msf;struct cdrom_volctrl volctrl;#ifdef AZT_PRIVATE_IOCTLSunion{ struct cdrom_msf msf; unsigned char buf[CD_FRAMESIZE_RAW];} azt;#endif AZT_PRIVATE_IOCTLSint i, i1, i2, i3, j, k;unsigned char sequence=0;unsigned char command[80];unsigned char first=1, last=1;char *default_device="/dev/cdrom";char dev[20];char filename[20];int drive;int datafile;int rc;void help(void){ printf("Available Commands:\n"); printf("STOP s EJECT e QUIT q\n"); printf("PLAY TRACK t PAUSE p RESUME r\n"); printf("NEXT TRACK n REPEAT LAST l HELP h\n"); printf("SUBCHANNEL_Q c TRACK INFO i PLAY AT a\n"); printf("READ d READ RAW w READ AUDIO A\n"); printf("MS-INFO M TOC T START S\n"); printf("SET EJECTSW X DEVICE D DEBUG Y\n"); printf("AUDIO_BUFSIZ Z RESET R BLKRASET B\n"); printf("SET VOLUME v GET VOLUME V\n");}/* * convert MSF number (3 bytes only) to Logical_Block_Address */int msf2lba(u_char *msf){ int i; i=(msf[0] * CD_SECS + msf[1]) * CD_FRAMES + msf[2] - CD_BLOCK_OFFSET; if (i<0) return (0); return (i);}/* * convert logical_block_address to m-s-f_number (3 bytes only) */void lba2msf(int lba, unsigned char *msf){ lba += CD_BLOCK_OFFSET; msf[0] = lba / (CD_SECS*CD_FRAMES); lba %= CD_SECS*CD_FRAMES; msf[1] = lba / CD_FRAMES; msf[2] = lba % CD_FRAMES;}int init_drive(char *dev){ unsigned char msf_ent[3]; /* * open the device */ drive=open(dev,0); if (drive<0) return (-1); /* * get TocHeader */ printf("getting TocHeader...\n"); rc=ioctl(drive,CDROMREADTOCHDR,&hdr); if (rc!=0) { printf("can't get TocHeader (error %d).\n",rc); return (-2); } else first=hdr.cdth_trk0; last=hdr.cdth_trk1; printf("TocHeader: %d %d\n",hdr.cdth_trk0,hdr.cdth_trk1); /* * get and display all TocEntries */ printf("getting TocEntries...\n"); for (i=1;i<=hdr.cdth_trk1+1;i++) { if (i!=hdr.cdth_trk1+1) TocEntry[i].cdte_track = i; else TocEntry[i].cdte_track = CDROM_LEADOUT; TocEntry[i].cdte_format = CDROM_LBA; rc=ioctl(drive,CDROMREADTOCENTRY,&TocEntry[i]); if (rc!=0) { printf("can't get TocEntry #%d (error %d).\n",i,rc); } else { lba2msf(TocEntry[i].cdte_addr.lba,&msf_ent[0]); if (TocEntry[i].cdte_track==CDROM_LEADOUT) { printf("TocEntry #%02X: %1X %1X %02d:%02d:%02d (lba: 0x%06X) %02X\n", TocEntry[i].cdte_track, TocEntry[i].cdte_adr, TocEntry[i].cdte_ctrl, msf_ent[0], msf_ent[1], msf_ent[2], TocEntry[i].cdte_addr.lba, TocEntry[i].cdte_datamode); } else { printf("TocEntry #%02d: %1X %1X %02d:%02d:%02d (lba: 0x%06X) %02X\n", TocEntry[i].cdte_track, TocEntry[i].cdte_adr, TocEntry[i].cdte_ctrl, msf_ent[0], msf_ent[1], msf_ent[2], TocEntry[i].cdte_addr.lba, TocEntry[i].cdte_datamode); } } } return (hdr.cdth_trk1); /* number of tracks */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -