The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

Написание программы для копирования треков с Audio-CD (cdrom audio sound gcc example)


<< Предыдущая ИНДЕКС Поиск в статьях src Установить закладку Перейти на закладку Следующая >>
Ключевые слова: cdrom, audio, sound, gcc, example,  (найти похожие документы)
From: Bob <ubob@mail.ru.> Newsgroups: email Date: Mon, 28 Jan 2005 14:31:37 +0000 (UTC) Subject: Написание программы для копирования треков с Audio-CD Копирование треков с Audio-CD В статье рассматривается исходный текст программы для считывания аудиоданных с музыкального компакт-диска (Audio-CD) и сохранения их в WAV-файле. Программа функционирует под управлением ОС Linux. Для понимания изложенного в статье материала необходимо знать структуру и форматы данных, хранящихся на компакт-диске. Эту информацию можно получить из следующих источников: 1. Information specification INF-8020i Rev 2.6. ATA Packet Interface for CD-ROMs SFF-8020i, http://www.stanford.edu/~csapuntz/specs/INF-8020.PDF 2. Introduction to CD and CD-ROM (with information on CD and CD-ROM formats, complete with diagrams and tables), http://www.disctronics.co.uk/downloads/tech_docs/cdintroduction.pdf 3. Крис Касперски. "Техника защиты компакт-дисков от копирования", издательство "BHV", 2004 г. 4. CD-Recordable FAQ, http://www.cdrfaq.org 5. Кулаков В. "Програмирование дисковых подсистем", издательство "Питер", 2002 г. 6. Comprising a comprehensive list of terms and words used in connection with CDs and DVDs and the applications that they support, http://www.disctronics.co.uk/downloads/tech_docs/glossary.pdf Заголовочные файлы: #include <stdio.h> #include <errno.h> #include <fcntl.h> #include <linux/cdrom.h> #include <linux/types.h> #include <sys/stat.h> #define CD_DEVICE "/dev/cdrom" // имя файла устройства #define WAV_HDR_LEN 44 // размер WAV-заголовка #define WAV_HDR_LEN 44 // размер WAV-заголовка Следующая структура описывает формат WAV-заголовка (взято из исх. текстов cdda2wav) typedef struct { __u8 riff[4]; __u32 size; __u8 wave[8]; __u32 size1; __u16 format_tag; __u16 channels; __u32 sample_per_sec; __u32 byte_per_sec; __u16 block_align; __u16 bit_per_sample; __u8 data[4]; __u32 size2; } __attribute__ ((packed)) wav_header_t; wav_header_t w_hdr; int main() { int fd, out, n; unsigned int i, start_lba, end_lba; unsigned int i, start_lba, end_lba; Буфер для аудиоданных: __u8 buff[CD_FRAMESIZE_RAW]; __u8 buff[CD_FRAMESIZE_RAW]; Значение CD_FRAMESIZE_RAW определено в файле <linux/cdrom.h>: #define CD_FRAMESIZE_RAW 2352 struct stat s; struct stat s; Следующие структуры определены в файле <linux/cdrom.h>: struct cdrom_tochdr hdr; struct cdrom_tocentry toc; struct cdrom_read_audio cda; struct cdrom_read_audio cda; Структура struct cdrom_tochdr содержит заголовок таблицы содержания диска (Table of Contents, TOC) - номера первого и последнего треков (см. спецификацию INF-8020i, стр.171, табл.127): /* This struct is used by the CDROMREADTOCHDR ioctl */ struct cdrom_tochdr { __u8 cdth_trk0; /* start track */ __u8 cdth_trk1; /* end track */ }; }; Структрура struct cdrom_tocentry содержит дескриптор трека (INF-8020i, стр.171, табл.127): /* This struct is used by the CDROMREADTOCENTRY ioctl */ struct cdrom_tocentry { __u8 cdte_track; __u8 cdte_adr :4; __u8 cdte_ctrl :4; __u8 cdte_format; union cdrom_addr cdte_addr; __u8 cdte_datamode; }; }; Поле cdte_track содержит номер трека, поле cdte_format определяет формат адреса - MSF (Minute/Second/Frame) или LBA. Значения этого поля определены в <linux/cdrom.h>: /* CD-ROM address types (cdrom_tocentry.cdte_format) */ #define CDROM_LBA 0x01 /* "logical block": first frame is #0 */ #define CDROM_MSF 0x02 /* "minute-second-frame": binary, not bcd here! */ #define CDROM_MSF 0x02 /* "minute-second-frame": binary, not bcd here! */ В зависимости от выбранного формата адреса используется одно из полей объединения union cdrom_addr: /* Address in either MSF or logical format */ union cdrom_addr { struct cdrom_msf0 msf; int lba; }; }; Структура struct cdrom_read_audio используется для хранения аудиоданных: /* This struct is used by the CDROMREADAUDIO ioctl */ struct cdrom_read_audio { union cdrom_addr addr; /* frame address */ __u8 addr_format; /* CDROM_LBA or CDROM_MSF */ int nframes; /* number of 2352-byte-frames to read at once */ __u8 *buf; /* frame buffer (size: nframes*2352 bytes) */ }; }; Открываем файл устройства: fd = open(CD_DEVICE, O_RDONLY|O_NONBLOCK); if(fd < 0) { perror("open"); return -1; } } Проверяем тип компакт-диска. Это должен быть Audio-CD: if(ioctl(fd, CDROM_DISC_STATUS) != CDS_AUDIO) { printf("I need Audio-CD!\n"); return 0; } } Определяем число треков на компакт-диске: memset((void *)&hdr, 0, sizeof(struct cdrom_tochdr)); if(ioctl(fd, CDROMREADTOCHDR, &hdr) < 0) { perror("ioctl"); return(errno); } printf("First: %d\t", hdr.cdth_trk0); printf("Last: %d\n", hdr.cdth_trk1); #define FIRST hdr.cdth_trk0 #define LAST hdr.cdth_trk1 #define LAST hdr.cdth_trk1 Вводим номер трека, который мы хотим считать с диска: printf("Enter track number: "); scanf("%d", &n); if((n < 1) || (n > LAST)) { printf("Wrong track number\n"); return -1; } } Задаем формат адреса LBA и считываем стартовые координаты трека: toc.cdte_format = CDROM_LBA; toc.cdte_track = n; if(ioctl(fd, CDROMREADTOCENTRY, &toc) < 0) { perror("ioctl"); return -1; } start_lba = toc.cdte_addr.lba; // стартовый адрес трека start_lba = toc.cdte_addr.lba; // стартовый адрес трека Конечный адрес трека определим как стартовый адрес следующего трека. Если мы выбрали последний трек на диске, то необходимо определить начало Lead-Out области диска if(n == LAST) toc.cdte_track = CDROM_LEADOUT; else toc.cdte_track = n + 1; if(ioctl(fd, CDROMREADTOCENTRY, &toc) < 0) { perror("ioctl"); return -1; } end_lba = toc.cdte_addr.lba; // конечный адрес трека end_lba = toc.cdte_addr.lba; // конечный адрес трека Создаем файл track.wav для хранения считанных аудиоданных: out = open("./track.wav", O_CREAT|O_RDWR|O_TRUNC, 0600); if(out < 0) { perror("open"); return -1; } } В начале файла должен находится заголовок установленного формата длиной 44 байта. Но так как нам пока неизвестны все значения полей заголовка (в частности, размер файла), запишем в файл пустой заголовок: memset(&w_hdr, 0, sizeof(wav_header_t)); write(out, (void *)&w_hdr, WAV_HDR_LEN); write(out, (void *)&w_hdr, WAV_HDR_LEN); Начинаем считывать аудиоданные. При каждом обращении к диску считываем один фрейм (2352 байта), адресация в формате LBA, считанные данные помещаем в буфер buff, а затем записываем в файл track.wav cda.addr_format = CDROM_LBA; cda.nframes = 1; cda.buf = buff; printf("Track size - %d sectors\n", end_lba - start_lba); for(i = start_lba; i < end_lba; i++) { memset(buff, 0, sizeof(buff)); cda.addr.lba = i; printf("%c", 0x0D); printf("lba: %u", i - start_lba + 1); /* Читаем аудиоданные*/ if(ioctl(fd, CDROMREADAUDIO, &cda) < 0) { perror("ioctl"); return -1; } if(write(out, (__u8 *)buff, CD_FRAMESIZE_RAW) < 0) { perror("write"); return -1; } } printf("\n"); printf("\n"); Определяем размер файла track.wav: memset(&s, 0, sizeof(struct stat)); if(fstat(out, &s) < 0) { perror("fstat"); exit(-1); } } Теперь необходимо сформировать WAV-заголовок и записать его в начало файла: memset(&w_hdr, 0, sizeof(wav_header_t)); memcpy(w_hdr.riff, "RIFF", 4); w_hdr.size = s.st_size - 8; memcpy(w_hdr.wave, "WAVEfmt ", 8); // последний символ - пробел w_hdr.size1 = 16; w_hdr.format_tag = 1; w_hdr.channels = 2; w_hdr.sample_per_sec = 44100; w_hdr.byte_per_sec = 176400; w_hdr.block_align = 4; w_hdr.bit_per_sample = 16; memcpy(w_hdr.data, "data", 4); w_hdr.size2 = s.st_size - WAV_HDR_LEN; w_hdr.size2 = s.st_size - WAV_HDR_LEN; Записываем сформированный заголовок в файл track.wav: lseek(out, 0, 0); write(out, (void *)&w_hdr, WAV_HDR_LEN); printf("OK\n"); close(fd); close(out); return 0; } } Полученный в результате работы программы файл track.wav можно сконвертировать в любой цифровой формат - MP3 или Ogg Vorbis, например: # oggenc -b 192 track.wav В результате получаем файл track.ogg, который можно прослушать при помощи утилиты ogg123: # ogg123 track.ogg Утилиты и библтотеки для работы с файлами формата Ogg Vorbis можно скачать с сайта http://www.vorbis.com.

<< Предыдущая ИНДЕКС Поиск в статьях src Установить закладку Перейти на закладку Следующая >>

Обсуждение [ RSS ]
  • 1, darkeagle (?), 01:09, 29/03/2005 [ответить]  
  • +/
    респект автору.
     

     Добавить комментарий
    Имя:
    E-Mail:
    Заголовок:
    Текст:




    Партнёры:
    PostgresPro
    Inferno Solutions
    Hosting by Hoster.ru
    Хостинг:

    Закладки на сайте
    Проследить за страницей
    Created 1996-2024 by Maxim Chirkov
    Добавить, Поддержать, Вебмастеру