2024年4月6日 星期六

linux 使用 ALSA lib 播放 mp3 檔

先上官網下載 minimp3 原始檔: https://github.com/lieff/minimp3

只需將檔案 minimp3.h 複製到專案目錄.  再編輯 mp3 播放主程式, 同樣透過 ALSA library 來播放:
// mp3play.cpp
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include "alsa/asoundlib.h"
#define MINIMP3_IMPLEMENTATION
#include "minimp3.h"

int main(int argc, char *argv[]) {
    const char *filename = (argc > 1) ? argv[1] : "test.mp3";
    int fd = open(filename, O_RDONLY);
    if (fd < 0) {
        printf("%s => not found\n", filename);
        return -1;
    }
    int fileLength = lseek(fd, 0, SEEK_END);
    unsigned char *fileMMAP = (unsigned char *) mmap(0, fileLength, PROT_READ, MAP_PRIVATE, fd, 0);
    int16_t speaker[MINIMP3_MAX_SAMPLES_PER_FRAME];

    mp3dec_frame_info_t info;
    mp3dec_t mp3decoder;
    mp3dec_init(&mp3decoder);
    int uframes = mp3dec_decode_frame(&mp3decoder, fileMMAP, fileLength, speaker, &info);// 1st frame to get channels && sampleRate
    if (uframes > 0) {
        printf("play uframes = %d, offset =%d, channels=%d, sampleRate=%d, frame_bytes=%d\n", uframes, info.frame_offset, info.channels, info.hz, info.frame_bytes);
        unsigned int channels = info.channels;
        unsigned int sampleRate = info.hz;
        snd_pcm_t *handle;
        if (snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0) == 0) { // hw:0,0 , default
            if (snd_pcm_set_params(handle, SND_PCM_FORMAT_S16_LE, SND_PCM_ACCESS_RW_INTERLEAVED, channels, sampleRate, 1, sampleRate / 4) == 0) {
                do {
                     const int err = snd_pcm_writei(handle, speaker, uframes);
                     if (err < 0) {
                         if (snd_pcm_recover(handle, err, 0) < 0) break;// alsa try to recover
                     }
                    fileMMAP += info.frame_bytes;// mp3 file position goes ahead
                    uframes = mp3dec_decode_frame(&mp3decoder, fileMMAP, uframes, speaker, &info);// is 1152 enough?
                } while (uframes > 0);
            }
            snd_pcm_close(handle);
        }
    }
    close(fd);
    return 0;
}
編譯並執行

      g++    mp3play.cpp    -lasound   &&   ./a.out

沒有留言:

張貼留言

使用 pcie 轉接器連接 nvme SSD

之前 AM4 主機板使用 pcie ssd, 但主機板故障了沒辦法上網, 只好翻出以前買的 FM2 舊主機板, 想辦法讓老主機復活, 但舊主機板沒有 nvme 的界面, 因此上網買了 pcie 轉接器用來連接 nvme ssd, 遺憾的是 grub2 bootloader 無法識...