Files
esp32s3_player/main/APP/player/audio_source.h
T

93 lines
3.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
****************************************************************************************************
* @file audio_source.h
* @author HiFi Player Project
* @version V1.5
* @date 2026-01-01
* @brief 统一音源接口(WAV / FLAC)
*
* 上层播放器只关心“给我一块立体声 PCM 和它对应的位宽”,不必区分容器格式:
*
* audio_source_open() ── 按文件头自动识别 RIFF(WAV) / fLaC、OggS(FLAC)
* │ 同时给出该曲目应使用的 I2S 位宽 out_bits(16/24/32)
* audio_source_read() ── 输出 **源文件原生位深** 的立体声交错 PCM
* │ 单声道自动复制;>2 声道只取前两声道;不做降位
* audio_source_close()
*
* 时间进度统一用“已播放帧数 / 采样率”计算,对两种格式都准确。
*
* 位宽映射(源位深 → I2S 位宽):
* ≤16bit → 16bit(每采样 2 字节)
* 17~24bit → 24bit(每采样 3 字节)
* 25~32bit → 32bit(每采样 4 字节)
* 非整字节位深(如 20bit)按左对齐放入更宽的槽位,音量不受影响。
*
* 采样率限制:
* ES8388 的 MCLK 由 I2S 产生(MCLK = mclk_multiple × fs),24bit 时
* mclk_multiple 必须是 384。若直接播放 192kHz,MCLK 会到 73.7MHz,
* 远超 codec 能力。因此 88.2k/96k/192k 等会做整数抽取降到 ≤48kHz,
* audio_info_t.sample_rate 返回的始终是「实际输出采样率」。
****************************************************************************************************
*/
#ifndef __AUDIO_SOURCE_H
#define __AUDIO_SOURCE_H
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/** 支持的音频容器 */
typedef enum {
AUDIO_CODEC_WAV = 0, /* RIFF/WAVE,PCM 16/24/32bit */
AUDIO_CODEC_FLAC, /* 原生 FLAC 或 Ogg FLAC */
} audio_codec_t;
/** 音源信息 */
typedef struct {
audio_codec_t codec; /* 容器类型 */
uint32_t sample_rate; /* 采样率 → 用于配置 I2S 频率(已按输出上限抽取) */
uint16_t bits; /* 源位深(界面显示用) */
uint16_t channels; /* 源声道数 */
uint16_t out_bits; /* I2S 输出位宽:16 / 24 / 32 */
uint8_t out_bytes; /* 输出每采样字节数:2 / 3 / 4 */
uint32_t total_sec; /* 总时长(秒),0 表示未知 */
} audio_info_t;
typedef struct audio_source audio_source_t;
/**
* @brief 打开音频文件并解析头部
* @param path 文件路径
* @param info 输出音源信息(可为 NULL)
* @retval 句柄;失败返回 NULL
*/
audio_source_t *audio_source_open(const char *path, audio_info_t *info);
/**
* @brief 读取一块 PCM
* @param src 音源句柄
* @param out 输出缓冲区(立体声交错,位宽 = info.out_bits)
* @param max_frames 最多读取多少帧(1 帧 = 左右各 1 个采样)
* @retval >0 实际帧数
* 0 播放结束
* <0 解码/读取错误
* @note 每帧占用 2 * out_bytes 字节,调用者需保证缓冲区足够
*/
int audio_source_read(audio_source_t *src, void *out, int max_frames);
/** @brief 已播放的秒数(按解码帧数计算) */
uint32_t audio_source_elapsed_sec(const audio_source_t *src);
/** @brief 关闭音源并释放资源(可传 NULL) */
void audio_source_close(audio_source_t *src);
#ifdef __cplusplus
}
#endif
#endif /* __AUDIO_SOURCE_H */