From 3f7e1f0492346557cb3d010c753d8077f588b602 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 16 Nov 2013 20:18:39 +0100 Subject: audio/format: add heuristic to estimate loss on format conversion The added function af_format_conversion_score() can be used to select the best sample format to convert to in order to reduce loss and extra conversion work. It calculates a "loss" score when going from one format to another, and for each conversion that needs to be done a certain score is subtracted. Thus, if you have to convert from one format to a set of other formats, you can calculate the score for each conversion, and pick the one with the highest score. Conversion between int and float is considered the worst case. One odd consequence is that when converting from s32 to u8 or float, u8 will be picked. Test program used to develop this follows: #define MAX_FMT 200 struct entry { const char *name; int score; }; static int compentry(const void *px1, const void *px2) { const struct entry *x1 = px1; const struct entry *x2 = px2; if (x1->score > x2->score) return 1; if (x1->score < x2->score) return -1; return 0; } int main(int argc, char *argv[]) { for (int n = 0; af_fmtstr_table[n].name; n++) { struct entry entry[MAX_FMT]; int entries = 0; for (int i = 0; af_fmtstr_table[i].name; i++) { assert(i < MAX_FMT); entry[entries].name = af_fmtstr_table[i].name; entry[entries].score = af_format_conversion_score(af_fmtstr_table[i].format, af_fmtstr_table[n].format); entries++; } qsort(&entry[0], entries, sizeof(entry[0]), compentry); for (int i = 0; i < entries; i++) { printf("%s -> %s: %d \n", af_fmtstr_table[n].name, entry[i].name, entry[i].score); } } } --- audio/format.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'audio/format.h') diff --git a/audio/format.h b/audio/format.h index 6542e1d12a..b318d4cdca 100644 --- a/audio/format.h +++ b/audio/format.h @@ -47,6 +47,7 @@ #define AF_FORMAT_SIGN_MASK (1<<1) // Bits used +// Some code assumes they're sorted by size. #define AF_FORMAT_8BIT (0<<3) #define AF_FORMAT_16BIT (1<<3) #define AF_FORMAT_24BIT (2<<3) @@ -164,4 +165,6 @@ bool af_fmt_is_valid(int format); void af_fill_silence(void *dst, size_t bytes, int format); +int af_format_conversion_score(int dst_format, int src_format); + #endif /* MPLAYER_AF_FORMAT_H */ -- cgit v1.2.3