1 Star 0 Fork 0

刘煜/opus-example

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
play.c 4.38 KB
一键复制 编辑 原始数据 按行查看 历史
刘煜 提交于 2025-04-16 15:54 +08:00 . 只计算一次帧大小
#include <alsa/asoundlib.h>
#include <opus/opus.h>
#define IFILE "record.opus"
struct player {
snd_pcm_t* device;
int channels;
int sample_rate;
int duration;
int frames;
OpusDecoder* decoder;
opus_int16* buffer;
};
struct player* player_create(const char* name, int sample_rate, int channels, int duration)
{
struct player* player = malloc(sizeof(struct player));
if (!player)
{
return NULL;
}
player->channels = channels;
player->sample_rate = sample_rate;
player->duration = duration;
int error = snd_pcm_open(&player->device, name, SND_PCM_STREAM_PLAYBACK, 0);
if (error < 0)
{
fprintf(stderr, "open %s failed: %s\n", name, snd_strerror(error));
free(player);
return NULL;
}
error = snd_pcm_set_params(player->device,
SND_PCM_FORMAT_S16_LE,
SND_PCM_ACCESS_RW_INTERLEAVED,
player->channels,
player->sample_rate,
1,
player->duration * 1000);
if (error < 0) {
fprintf(stderr, "snd_pcm_set_params: %s\n", snd_strerror(error));
snd_pcm_close(player->device);
free(player);
return NULL;
}
player->decoder = opus_decoder_create(player->sample_rate, player->channels, &error);
if (error != OPUS_OK) {
fprintf(stderr, "opus_decoder_create: %s\n", opus_strerror(error));
snd_pcm_close(player->device);
free(player);
return NULL;
}
player->frames = player->sample_rate * player->duration / 1000;
player->buffer = malloc(snd_pcm_frames_to_bytes(player->device, player->frames));
if (!player->buffer) {
opus_decoder_destroy(player->decoder);
snd_pcm_close(player->device);
free(player);
return NULL;
}
return player;
}
void player_destroy(struct player *player)
{
if (player) {
if (player->buffer) {
free(player->buffer);
player->buffer = NULL;
}
if (player->device) {
snd_pcm_close(player->device);
player->device = NULL;
}
if (player->decoder) {
opus_decoder_destroy(player->decoder);
player->decoder = NULL;
}
free(player);
}
}
int player_start(struct player *player)
{
if (!player)
{
return -1;
}
return snd_pcm_start(player->device);
}
int player_stop(struct player *player)
{
if (!player)
{
return -1;
}
return snd_pcm_drain(player->device);
}
int play_audio(struct player* player, char* data, size_t size)
{
if (!player)
{
return -1;
}
int dec_frames = opus_decode(player->decoder, data, size, player->buffer, player->frames, 0);
if (dec_frames < 0) {
fprintf(stderr, "opus_decode: %s\n", opus_strerror(dec_frames));
return -1;
}
snd_pcm_sframes_t frames = snd_pcm_writei(player->device, player->buffer, dec_frames);
if (frames < 0) {
fprintf(stderr, "snd_pcm_writei: %s\n", snd_strerror(frames));
return -1;
}
return 0;
}
char file_buffer[4096];
int main()
{
FILE *fp = fopen(IFILE, "rb");
if (!fp)
{
perror(IFILE);
return EXIT_FAILURE;
}
struct player* player = player_create("default", 16000, 1, 20);
if (!player)
{
fclose(fp);
return EXIT_FAILURE;
}
player_start(player);
while (1) {
int32_t rbytes;
// 读取帧头
if (fread(&rbytes, 1, sizeof(rbytes), fp) != sizeof(rbytes))
{
if (feof(fp))
{
puts("Playback complete");
}
else
{
perror("fread");
}
break;
}
if (rbytes > sizeof(file_buffer))
{
fprintf(stderr, "Frame size %d too large\n", rbytes);
break;
}
size_t bytes = fread(file_buffer, 1, rbytes, fp);
if (bytes != rbytes) {
fprintf(stderr, "expect %d bytes, got %d bytes\n", rbytes, bytes);
break;
}
printf("read %d bytes\n", bytes);
if (play_audio(player, file_buffer, bytes) < 0)
{
continue;
}
}
player_stop(player);
player_destroy(player);
fclose(fp);
return EXIT_SUCCESS;
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/tinytaro/opus-example.git
git@gitee.com:tinytaro/opus-example.git
tinytaro
opus-example
opus-example
master

搜索帮助