Files
MeowOS-For-R3P2/patch_v2/ncm_app/app/test/test_decode.c
T
MeowOS 70aec677ce ncm: FLAC 解码落地(dr_flac 0.13.4 单头入库) + 缓存键=歌曲ID+音质档位
- 解码分发 decoder.c:magic(fLaC→dr_flac / 其它→minimp3);flac ≤16bit→S16、
  >16bit→S32 满幅送 audiod(AUDIO_FMT_S32),rate/ch/bits 按实际流,零 SRC 零裁剪
- song_url_auto 接受 flac(type 权威/url 扩展名兜底),降级语义不变;flac 下载限幅 1GB
- 缓存键 song_<id>_<level>.<ext>:同歌同档命中不重下,换档新条目旧档留 LRU;
  ext 前导点正名(修双点名),lookup 回退历史双点名+旧无档键温和兼容
- audio_out S32 通路(AUDIOD/ALSA/WAV)+ 流死重开按 bits 还原格式
- 验证(0 真实请求):44.1k/16 与 96k/24 自制样本宿主+qemu 帧数/时长精确、
  逐样本零误差;mp3 回归逐帧一致;player_flow_sim P1-P6(新 P6 档位键/flac ext)、
  cache_evict/cover/pagination/window/audiod_chain sim 全 PASS;mipsel 0 warning
- REPORT §19 / VENDOR_NOTES dr_flac 条目;未部署真机(留主会话)
2026-09-01 14:14:38 +08:00

91 lines
3.8 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.
/* test/test_decode.c — 播放解码链路验证(宿主/mipsel+qemu):decoder(magic 分发
* dr_flac/minimp3,§19)→ audio_out(FILE sink) 写 WAV。不依赖网络/登录(输入本地文件)。
* 验证:格式探测正确、rate/ch/bits 按实际流、解码无错、WAV 非空、帧数/时长对、RT 因子。
*
* 运行:NCM_AUDIO_SINK=file NCM_AUDIO_OUT=/tmp/ncm_decode.wav \
* ./test_decode <path> [expect_frames] [expect_rate] [expect_bits]
* expect_* 给定时校验(不一致 exit 1);不给则只要求 frames>0。
*
* 编译(宿主,ncm_app 目录下):
* gcc -O2 -Wall -Wextra -DJSMN_HEADER -I. -Icore -I../sdk -I../meow_launcherd \
* -Ivendor/minimp3 -Ivendor/dr_flac \
* app/test/test_decode.c app/play/decoder.c app/play/audio_out.c \
* ../sdk/meow_ui_audio.c ../sdk/meow_ui_log.c -o /tmp/td.o-chain # 见下两行豁免 TU
* gcc -O2 -Ivendor/minimp3 -c app/play/minimp3_impl.c -o /tmp/td_mm.o # vendor 豁免
* gcc -O2 -Ivendor/dr_flac -c app/play/dr_flac_impl.c -o /tmp/td_df.o # vendor 豁免
* (首行改为 -c 逐个或把两个豁免 .o 一并链接:gcc ... -o out/test_decode /tmp/td_mm.o /tmp/td_df.o -lpthread -lm)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "../ncm_app_internal.h" /* audio_out 声明 + 全局态 */
#include "../play/decoder.h"
ncm_app_state_t g_st;
ncm_play_run_t g_play = { .mu = PTHREAD_MUTEX_INITIALIZER };
volatile int g_app_quit = 0;
volatile int g_net_ready = 0;
int g_host_mock = 1;
/* SDK meow_ui_log.c 需要(本测试不链 meow_ui_sys.c,同 audiod_chain_sim 口径打桩) */
uint64_t meow_ui_time_ms(void)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
}
static double now_s(void)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (double)ts.tv_sec + ts.tv_nsec / 1e9;
}
int main(int argc, char **argv)
{
const char *path = (argc > 1) ? argv[1] : "vendor/minimp3/vectors/performance/MIPSTest.mp3";
int64_t exp_frames = (argc > 2) ? atoll(argv[2]) : -1;
int exp_rate = (argc > 3) ? atoi(argv[3]) : -1;
int exp_bits = (argc > 4) ? atoi(argv[4]) : -1;
ncm_decoder_t *dec = NULL;
int rate = 0, ch = 0, bits = 0;
int64_t total_frames = 0;
if (ncm_dec_open(&dec, path, &rate, &ch, &bits, &total_frames) != 0) {
fprintf(stderr, "open failed\n"); return 1;
}
printf("%s: %s %dHz x%d %dbit total_frames=%lld\n",
path, ncm_dec_format(dec), rate, ch, bits, (long long)total_frames);
if (exp_rate > 0 && rate != exp_rate) { fprintf(stderr, "rate mismatch %d != %d\n", rate, exp_rate); return 1; }
if (exp_bits > 0 && bits != exp_bits) { fprintf(stderr, "bits mismatch %d != %d\n", bits, exp_bits); return 1; }
if (audio_out_open(rate, ch, bits) != 0) { fprintf(stderr, "audio_out open failed\n"); return 1; }
static int32_t pcm[4096 * 2];
long long frames = 0;
double t0 = now_s();
for (;;) {
if (g_app_quit) break;
int64_t got = ncm_dec_read(dec, pcm, 4096);
if (got == 0) break;
if (audio_out_write(pcm, (int)got) != (int)got) { fprintf(stderr, "write failed\n"); break; }
frames += got;
}
double dt = now_s() - t0;
audio_out_close();
ncm_dec_close(dec);
double secs = rate > 0 ? (double)frames / (double)rate : 0;
double rt = (dt > 0) ? secs / dt : 0;
printf("decoded %lld frames = %.3f s audio (%d Hz) in %.3f s => %.1fx RT\n",
frames, secs, rate, dt, rt);
if (exp_frames >= 0 && frames != exp_frames) {
fprintf(stderr, "frames mismatch %lld != %lld\n", frames, (long long)exp_frames);
return 1;
}
printf("OK: %s\n", (frames > 0) ? "decode chain works" : "EMPTY");
return (frames > 0) ? 0 : 1;
}