/* play/decoder.h — 格式分发解码(REPORT §19):按文件 magic 选后端。 * "fLaC" → dr_flac(无损 SQ / Hi-Res,vendor/dr_flac.h) * 其它(ID3 / 0xFF 帧同步 / 未知)→ minimp3(既有 mp3 路径,未知格式由 minimp3 兜底报错) * 输出约定:bits<=16 → 交织 S16;bits>16 → 交织 S32(dr_flac s32 左对齐满幅,送 audiod * AUDIO_FMT_S32,AUDIOD_DESIGN.md §4 格式归一由 SDK/audiod 完成,本层不做 SRC/裁剪)。 */ #ifndef NCM_DECODER_H #define NCM_DECODER_H #include #include "stream_src.h" #ifdef __cplusplus extern "C" { #endif typedef struct ncm_decoder ncm_decoder_t; /* 在 stream_src 上打开并探测流参数(边下边播/缓存命中统一入口,§21): * magic 经 stream_src_peek 探测;mp3=mp3dec_ex_open_cb(MP3D_SEEK_TO_BYTE|MP3D_DO_NOT_SCAN, * F3 红线:不带 DO_NOT_SCAN 会全流扫描阻塞到下载结束);flac=drflac_open 回调模式。 * src 由调用方持有(dec_close 不关闭 src)。rate/ch/bits/total_frames 经指针回填 * (mp3 恒 16bit;total_frames 0=未知)。返回 0=成功。 */ int ncm_dec_open_src(ncm_decoder_t **out, stream_src_t *src, int *rate, int *ch, int *bits, int64_t *total_frames); /* 整文件路径便捷入口:内部建 final=size 的静态 stream_src(dec_close 一并释放)。 * 解码同样走 cb 路径(不 mmap 整文件,P1 修复),输出与 ncm_dec_open_src 一致。 */ int ncm_dec_open(ncm_decoder_t **out, const char *path, int *rate, int *ch, int *bits, int64_t *total_frames); /* 读最多 cap_frames 帧到 buf(交织,样本位宽=open 返回的 bits;cap 以帧计, * buf 容量须 ≥ cap_frames*ch*(bits/8))。返回实际帧数,0=EOF。 */ int64_t ncm_dec_read(ncm_decoder_t *d, void *buf, int64_t cap_frames); /* seek 到 ms。flac=精确 PCM 帧;mp3=按 file_bytes*ms/dur_ms 字节近似(同旧语义)。 * 流模式下 seek 目标超已下载区时读端自然阻塞等待(F4),不报错。 */ int ncm_dec_seek_ms(ncm_decoder_t *d, int64_t ms, int64_t file_bytes, int64_t dur_ms); void ncm_dec_close(ncm_decoder_t *d); /* "mp3" / "flac"(日志/UI 用)。 */ const char *ncm_dec_format(const ncm_decoder_t *d); #ifdef __cplusplus } #endif #endif /* NCM_DECODER_H */