るみさんのブログ

【備忘録】Linux上でC言語を使って音楽CDを再生する

作成日:2024-12-01 22:34:06
最新更新日:2024-12-06 04:52:03

はじめに


多分もっといいやり方有ると思います、ChatGPTに聞きながら頑張りました。。。
あと、私のコードは個性が強いです、なので使うときはあなた達の個性に合わせて変換してください。

結論


(このためにコードを手直ししてます)
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <linux/cdrom.h> #include <sys/ioctl.h> #include <alsa/asoundlib.h> //CDのデバイスファイル #define CDROM_DEVICE "/dev/cdrom" //1フレームあたりのバイト数 #define FRAME_SIZE 2352 //CDの標準サンプルレート #define SAMPLE_RATE 44100 //チャンネル数(2でステレオ、1でモノラル、大体2) #define CHANNELS 2 int main() { int FD = open(CDROM_DEVICE, O_RDONLY); if (FD == -1) { perror("CDを開けませんでした"); return 1; } struct cdrom_tochdr tochdr; if (ioctl(FD, CDROMREADTOCHDR, &tochdr) == -1) { perror("TOCを読み込めませんでした"); close(FD); return 1; } printf("トラック数%d〜%d\n", tochdr.cdth_trk0, tochdr.cdth_trk1); //読み込みたいトラック番号 int TRACK = 1; if (TRACK < tochdr.cdth_trk0 || TRACK > tochdr.cdth_trk1) { fprintf(stderr, "トラック番号が不正です: %d\n", TRACK); close(FD); return 1; } //トラック情報を取得 struct cdrom_tocentry tocentry_start, tocentry_end; tocentry_start.cdte_track = TRACK; tocentry_start.cdte_format = CDROM_LBA; tocentry_end.cdte_track = TRACK + 1; tocentry_end.cdte_format = CDROM_LBA; if (ioctl(FD, CDROMREADTOCENTRY, &tocentry_start) == -1 || ioctl(FD, CDROMREADTOCENTRY, &tocentry_end) == -1) { perror("TOCのエントリーを読み込めませんでした"); close(FD); return 1; } int START_LBA = tocentry_start.cdte_addr.lba; int END_LBA = tocentry_end.cdte_addr.lba; printf("トラック:%d: LBA%dから%d\n", TRACK, START_LBA, END_LBA - 1); //ALSAを初期化 snd_pcm_t *PCM_HANDLE; snd_pcm_hw_params_t *PARAM; int ERR; if ((ERR = snd_pcm_open(&PCM_HANDLE, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0) { fprintf(stderr, "PCMデバイスを開けませんでした: %s\n", snd_strerror(ERR)); close(FD); return 1; } snd_pcm_hw_params_malloc(&PARAM); snd_pcm_hw_params_any(PCM_HANDLE, PARAM); snd_pcm_hw_params_set_access(PCM_HANDLE, PARAM, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(PCM_HANDLE, PARAM, SND_PCM_FORMAT_S16_LE); snd_pcm_hw_params_set_channels(PCM_HANDLE, PARAM, CHANNELS); snd_pcm_hw_params_set_rate(PCM_HANDLE, PARAM, SAMPLE_RATE, 0); if ((ERR = snd_pcm_hw_params(PCM_HANDLE, PARAM)) < 0) { fprintf(stderr, "死: %s\n", snd_strerror(ERR)); snd_pcm_close(PCM_HANDLE); close(FD); return 1; } snd_pcm_hw_params_free(PARAM); //トラックを読み取る int nFLAME = 10; char BUFFER[FRAME_SIZE * nFLAME]; struct cdrom_read_audio audio_data; audio_data.addr_format = CDROM_LBA; audio_data.nframes = nFLAME; audio_data.buf = BUFFER; for (int lba = START_LBA; lba < END_LBA; lba += nFLAME) { audio_data.addr.lba = lba; if (ioctl(FD, CDROMREADAUDIO, &audio_data) == -1) { perror("オーディオデータを読めませんでした"); break; } printf("%dから%dを読み込みました\n", lba, lba + nFLAME - 1 > END_LBA ? END_LBA : lba + nFLAME - 1); //ALSAに流し込む if ((ERR = snd_pcm_writei(PCM_HANDLE, BUFFER, nFLAME * (FRAME_SIZE / 4))) < 0) { fprintf(stderr, "Playback error: %s\n", snd_strerror(ERR)); snd_pcm_prepare(PCM_HANDLE); } } //終了処理 snd_pcm_drain(PCM_HANDLE); snd_pcm_close(PCM_HANDLE); close(FD); return 0; }


実演


Youtubeに再生動画上げました↓
https://youtu.be/0W8t_TxYlfg
もしかしたら消えてる可能性有るので一応此処にも

説明欄
うちのMisskey鯖が雑魚すぎてでかい動画は無理なので、Youtubeに、、、 いつかブログに書く予定です、書いたらここに載せますね! 倫理的に音質をひどいぐらい劣化させてます、カセットテープ理論です、 カセットテープ理論っていうのは、昔は曲をダビングして友達に渡すのは合法だったんですよ、なぜならカセットテープはコピーすれば劣化するので、、、 その理論をデジタル社会の今に使ったわけです、どうです?ひどいほど劣化してるでしょう


終わり


あとは矢印キーでの操作でも搭載すればいい感じだと思います、、、
Python + ラズパイで、ボタン操作とかも実装してもいいかもしれない、私はそうする
Pythonではないけど、Javaだけど



シェア



コメント欄の復旧は少し待ってね