鱼C论坛

 找回密码
 立即注册
查看: 1943|回复: 6

[已解决]Mac系统C++如何播放MP3?

[复制链接]
发表于 2021-9-4 17:45:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
Mac系统下C++无法使用Windows.h头文件的Beep,该如何播放MP3呢?
最好是C++自带的头文件,如果不是,请写下头文件的下载地址哦
最佳答案
2021-9-6 15:48:12
下面这个代码花了我大概三天的时间,因为学到了很多东西,所以值得,^_^

音频视频处理领域,ffmpeg 大概是最权威的了
ffmpeg 跨平台,mac 肯定能用
我的程序中还使用了 /dev/dsp 设备,不知道 mac 能不能用
这个程序把解码出来的音频数据发往 dsp 设备,如果 dsp 设备不能用,那就使用 sdl,把发往 dsp 的数据发送到 sdl 进行播放
还有,因为使用了 ffmpeg,这个程序可不仅仅支持 mp3,ffmpeg 支持绝大多数的音频视频格式
还有,我刚刚才看到是要求 C++ 写,C语言代码在下面,如果你真的必须是要 C++ 的话,自己改代码吧,^_^
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/soundcard.h>
#include <libavformat/avformat.h>
#include <libavcodec/codec.h>
#include <libswresample/swresample.h>

int main(int argc, char *argv[]) {
    if(argc != 2) return -1;
    const char *filename = argv[1];
    AVFormatContext *format_ctx = avformat_alloc_context();
    avformat_open_input(&format_ctx, filename, NULL, NULL);
    avformat_find_stream_info(format_ctx, NULL);
    int stream_idx = av_find_best_stream(format_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
    AVCodecParameters *codecpar = format_ctx->streams[stream_idx]->codecpar;
    AVCodec *codec = avcodec_find_decoder(codecpar->codec_id);
    AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
    avcodec_parameters_to_context(codec_ctx, codecpar);
    avcodec_open2(codec_ctx, codec, NULL);

    int dsp = open("/dev/dsp", O_WRONLY);
    int channels = codecpar->channels;
    int sample_rate = codecpar->sample_rate;
    int sample_fmt = AFMT_S16_LE;   // dsp 有好多格式都不支持,这里使用固定格式,下面把数据转换到这个格式
    ioctl(dsp, SNDCTL_DSP_CHANNELS, &channels);
    ioctl(dsp, SNDCTL_DSP_SPEED, &sample_rate);
    ioctl(dsp, SNDCTL_DSP_SETFMT, &sample_fmt);
    printf("channels: %d, sample_rate: %d, sample_fmt: %d\n", channels, sample_rate,
            av_get_bytes_per_sample(codecpar->format) * 8);
    SwrContext *swr_ctx = swr_alloc();
    int channel_layout = av_get_default_channel_layout(codecpar->channels);     // codecpar->channel_layout 有可能为 0
    swr_alloc_set_opts(swr_ctx, channel_layout, AV_SAMPLE_FMT_S16, codecpar->sample_rate,
            channel_layout, codecpar->format, codecpar->sample_rate, 0, NULL);
    swr_init(swr_ctx);
    AVPacket *pkt = av_packet_alloc();
    AVFrame *frame = av_frame_alloc();
    size_t buffer_size = 48000 * 4;
    uint8_t *buffer = av_malloc(buffer_size);
    while(av_read_frame(format_ctx, pkt) == 0) {
        if(pkt->stream_index == stream_idx) {
            avcodec_send_packet(codec_ctx, pkt);
            avcodec_receive_frame(codec_ctx, frame);
            swr_convert(swr_ctx, &buffer, buffer_size, (const uint8_t **)&frame->data[0], frame->nb_samples);
            ssize_t nbytes = av_samples_get_buffer_size(NULL, codecpar->channels, frame->nb_samples, AV_SAMPLE_FMT_S16, 1);
            write(dsp, buffer, nbytes);
        }
        av_packet_unref(pkt);
    }
    av_free(buffer);
    av_frame_free(&frame);
    av_packet_free(&pkt);
    swr_free(&swr_ctx);
    close(dsp);

    avcodec_close(codec_ctx);
    avcodec_free_context(&codec_ctx);
    avformat_close_input(&format_ctx);
    avformat_free_context(format_ctx);
    return 0;
}

编译命令
gcc -g -Wall -o main main.c -lavformat -lavcodec -lavutil -lswresample

运行
./main test.mp3
./main test.mp4
./main test.aac
./main test.flv
...

写这个代码参考了下面这些内容,当然肯定不止这些,我没办法全部列出了
https://www.baidu.com/
https://blog.csdn.net/dux003/article/details/5459423
https://www.jianshu.com/p/8ff162ac55bd
https://www.jianshu.com/p/2f2b8e0fe540
https://stackoverflow.com/questi ... float-planar-to-s16
https://cloud.tencent.com/developer/article/1666126
https://blog.csdn.net/woai110120130/article/details/82080648
https://blog.csdn.net/huohongpeng/article/details/119670171
https://www.jb51.net/article/201684.htm
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-9-4 21:46:40 | 显示全部楼层
Windows的程序我也在Mac上运行不了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-9-5 11:22:53 | 显示全部楼层
mei-mo 发表于 2021-9-4 21:46
Windows的程序我也在Mac上运行不了

我也是

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-9-5 13:04:55 | 显示全部楼层
mei-mo 发表于 2021-9-4 21:46
Windows的程序我也在Mac上运行不了

可能系统不一样吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-9-5 21:34:22 | 显示全部楼层
mei-mo 发表于 2021-9-4 21:46
Windows的程序我也在Mac上运行不了

你指的是exe吗……
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-9-6 15:48:12 | 显示全部楼层    本楼为最佳答案   
下面这个代码花了我大概三天的时间,因为学到了很多东西,所以值得,^_^

音频视频处理领域,ffmpeg 大概是最权威的了
ffmpeg 跨平台,mac 肯定能用
我的程序中还使用了 /dev/dsp 设备,不知道 mac 能不能用
这个程序把解码出来的音频数据发往 dsp 设备,如果 dsp 设备不能用,那就使用 sdl,把发往 dsp 的数据发送到 sdl 进行播放
还有,因为使用了 ffmpeg,这个程序可不仅仅支持 mp3,ffmpeg 支持绝大多数的音频视频格式
还有,我刚刚才看到是要求 C++ 写,C语言代码在下面,如果你真的必须是要 C++ 的话,自己改代码吧,^_^
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/soundcard.h>
#include <libavformat/avformat.h>
#include <libavcodec/codec.h>
#include <libswresample/swresample.h>

int main(int argc, char *argv[]) {
    if(argc != 2) return -1;
    const char *filename = argv[1];
    AVFormatContext *format_ctx = avformat_alloc_context();
    avformat_open_input(&format_ctx, filename, NULL, NULL);
    avformat_find_stream_info(format_ctx, NULL);
    int stream_idx = av_find_best_stream(format_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
    AVCodecParameters *codecpar = format_ctx->streams[stream_idx]->codecpar;
    AVCodec *codec = avcodec_find_decoder(codecpar->codec_id);
    AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
    avcodec_parameters_to_context(codec_ctx, codecpar);
    avcodec_open2(codec_ctx, codec, NULL);

    int dsp = open("/dev/dsp", O_WRONLY);
    int channels = codecpar->channels;
    int sample_rate = codecpar->sample_rate;
    int sample_fmt = AFMT_S16_LE;   // dsp 有好多格式都不支持,这里使用固定格式,下面把数据转换到这个格式
    ioctl(dsp, SNDCTL_DSP_CHANNELS, &channels);
    ioctl(dsp, SNDCTL_DSP_SPEED, &sample_rate);
    ioctl(dsp, SNDCTL_DSP_SETFMT, &sample_fmt);
    printf("channels: %d, sample_rate: %d, sample_fmt: %d\n", channels, sample_rate,
            av_get_bytes_per_sample(codecpar->format) * 8);
    SwrContext *swr_ctx = swr_alloc();
    int channel_layout = av_get_default_channel_layout(codecpar->channels);     // codecpar->channel_layout 有可能为 0
    swr_alloc_set_opts(swr_ctx, channel_layout, AV_SAMPLE_FMT_S16, codecpar->sample_rate,
            channel_layout, codecpar->format, codecpar->sample_rate, 0, NULL);
    swr_init(swr_ctx);
    AVPacket *pkt = av_packet_alloc();
    AVFrame *frame = av_frame_alloc();
    size_t buffer_size = 48000 * 4;
    uint8_t *buffer = av_malloc(buffer_size);
    while(av_read_frame(format_ctx, pkt) == 0) {
        if(pkt->stream_index == stream_idx) {
            avcodec_send_packet(codec_ctx, pkt);
            avcodec_receive_frame(codec_ctx, frame);
            swr_convert(swr_ctx, &buffer, buffer_size, (const uint8_t **)&frame->data[0], frame->nb_samples);
            ssize_t nbytes = av_samples_get_buffer_size(NULL, codecpar->channels, frame->nb_samples, AV_SAMPLE_FMT_S16, 1);
            write(dsp, buffer, nbytes);
        }
        av_packet_unref(pkt);
    }
    av_free(buffer);
    av_frame_free(&frame);
    av_packet_free(&pkt);
    swr_free(&swr_ctx);
    close(dsp);

    avcodec_close(codec_ctx);
    avcodec_free_context(&codec_ctx);
    avformat_close_input(&format_ctx);
    avformat_free_context(format_ctx);
    return 0;
}

编译命令
gcc -g -Wall -o main main.c -lavformat -lavcodec -lavutil -lswresample

运行
./main test.mp3
./main test.mp4
./main test.aac
./main test.flv
...

写这个代码参考了下面这些内容,当然肯定不止这些,我没办法全部列出了
https://www.baidu.com/
https://blog.csdn.net/dux003/article/details/5459423
https://www.jianshu.com/p/8ff162ac55bd
https://www.jianshu.com/p/2f2b8e0fe540
https://stackoverflow.com/questi ... float-planar-to-s16
https://cloud.tencent.com/developer/article/1666126
https://blog.csdn.net/woai110120130/article/details/82080648
https://blog.csdn.net/huohongpeng/article/details/119670171
https://www.jb51.net/article/201684.htm
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-10-2 11:29:38 | 显示全部楼层
人造人 发表于 2021-9-6 15:48
下面这个代码花了我大概三天的时间,因为学到了很多东西,所以值得,^_^

音频视频处理领域,ffmpeg 大概 ...

谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-22 12:27

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表