📄 rawaudioguess.cpp
字号:
signvotes++; else unsignvotes++; } #if RAW_GUESS_DEBUG fprintf(af, "sign: %d unsign: %d\n", signvotes, unsignvotes); #endif if (signvotes > unsignvotes) guessSigned = true; else guessSigned = false; #if RAW_GUESS_DEBUG if (guessSigned) fprintf(af, "signed\n"); else fprintf(af, "unsigned\n"); #endif /* Finally we test stereo/mono. We use the same JumpStat, and say * that the file is stereo if and only if for the majority of the * tests, the left channel and the right channel are more smooth than * the entire stream interpreted as one channel. */ for (test = 0; test < numTests; test++) { float leftChannel, rightChannel, combinedChannel; Extract(0, guessSigned, 1, 0, 0, rawData[test], dataSize, data1, data2, &len1, &len2); leftChannel = JumpStat(data1, len1); rightChannel = JumpStat(data2, len2); Extract(0, guessSigned, 0, 0, 0, rawData[test], dataSize, data1, data2, &len1, &len2); combinedChannel = JumpStat(data1, len1); if (leftChannel > combinedChannel && rightChannel > combinedChannel) stereoVotes++; else monoVotes++; } #if RAW_GUESS_DEBUG fprintf(af, "stereo: %d mono: %d\n", stereoVotes, monoVotes); #endif if (stereoVotes > monoVotes) guessStereo = true; else guessStereo = false; if (guessStereo == false) { /* test for repeated-byte, redundant stereo */ int rstereoVotes = 0; int rmonoVotes = 0; for (test = 0; test < numTests; test++) { float redundant; Extract(0, guessSigned, 0, 0, 0, rawData[test], dataSize, data1, data2, &len1, &len2); redundant = RedundantStereo(data1, len1); #if RAW_GUESS_DEBUG fprintf(af, "redundant: %f\n", redundant); #endif if (redundant > 0.8) rstereoVotes++; else rmonoVotes++; } #if RAW_GUESS_DEBUG fprintf(af, "rstereo: %d rmono: %d\n", rstereoVotes, rmonoVotes); #endif if (rstereoVotes > rmonoVotes) guessStereo = true; } #if RAW_GUESS_DEBUG if (guessStereo) fprintf(af, "stereo\n"); else fprintf(af, "mono\n"); #endif free(data1); free(data2); if (guessStereo) *out_channels = 2; else *out_channels = 1; if (guessSigned) return SF_FORMAT_RAW | SF_FORMAT_PCM_S8; else return SF_FORMAT_RAW | SF_FORMAT_PCM_U8;}int Guess16Bit(int numTests, char **rawData, int dataSize, bool evenMSB, int *out_offset, int *out_channels){ int format; bool guessSigned = false; bool guessStereo = false; bool guessBigEndian = false; bool guessOffset = false; int signvotes = 0; int unsignvotes = 0; int stereoVotes = 0; int monoVotes = 0; int formerVotes = 0; int latterVotes = 0; char *rawData2 = (char *)malloc(dataSize + 4); float *data1 = (float *)malloc((dataSize + 4) * sizeof(float)); float *data2 = (float *)malloc((dataSize + 4) * sizeof(float)); int len1; int len2; int test; #if RAW_GUESS_DEBUG FILE *af = g_raw_debug_file; fprintf(af, "16-bit\n"); #endif /* * Do the signed/unsigned test by using only the MSB. */ for (test = 0; test < numTests; test++) { float signL, signR, unsignL, unsignR; int i; /* Extract a new array of the MSBs only: */ for (i = 0; i < dataSize / 2; i++) rawData2[i] = rawData[test][2 * i + (evenMSB ? 0 : 1)]; /* Test signed/unsigned of the MSB */ Extract(0, 1, 1, 0, /* 8-bit signed stereo */ 0, rawData2, dataSize / 2, data1, data2, &len1, &len2); signL = JumpStat(data1, len1); signR = JumpStat(data2, len2); Extract(0, 0, 1, 0, /* 8-bit unsigned stereo */ 0, rawData2, dataSize / 2, data1, data2, &len1, &len2); unsignL = JumpStat(data1, len1); unsignR = JumpStat(data2, len2); if (signL > unsignL) signvotes++; else unsignvotes++; if (signR > unsignR) signvotes++; else unsignvotes++; } #if RAW_GUESS_DEBUG fprintf(af, "sign: %d unsign: %d\n", signvotes, unsignvotes); #endif if (signvotes > unsignvotes) guessSigned = true; else guessSigned = false; #if RAW_GUESS_DEBUG if (guessSigned) fprintf(af, "signed\n"); else fprintf(af, "unsigned\n"); #endif /* * Test mono/stereo using only the MSB */ for (test = 0; test < numTests; test++) { float leftChannel, rightChannel, combinedChannel; int i; /* Extract a new array of the MSBs only: */ for (i = 0; i < dataSize / 2; i++) rawData2[i] = rawData[test][2 * i + (evenMSB ? 0 : 1)]; Extract(0, guessSigned, 1, 0, 0, rawData2, dataSize / 2, data1, data2, &len1, &len2); leftChannel = JumpStat(data1, len1); rightChannel = JumpStat(data2, len2); Extract(0, guessSigned, 0, 0, 0, rawData2, dataSize / 2, data1, data2, &len1, &len2); combinedChannel = JumpStat(data1, len1); if (leftChannel > combinedChannel && rightChannel > combinedChannel) stereoVotes++; else monoVotes++; } #if RAW_GUESS_DEBUG fprintf(af, "stereoVotes: %d monoVotes: %d\n", stereoVotes, monoVotes); #endif if (stereoVotes > monoVotes) guessStereo = true; else guessStereo = false; if (guessStereo == false) { /* Test for repeated-byte, redundant stereo */ int rstereoVotes = 0; int rmonoVotes = 0; for (test = 0; test < numTests; test++) { float redundant; int i; /* Extract a new array of the MSBs only: */ for (i = 0; i < dataSize / 2; i++) rawData2[i] = rawData[test][2 * i + (evenMSB ? 0 : 1)]; Extract(0, guessSigned, 0, 0, 0, rawData2, dataSize / 2, data1, data2, &len1, &len2); redundant = RedundantStereo(data1, len1); if (redundant > 0.8) rstereoVotes++; else rmonoVotes++; } #if RAW_GUESS_DEBUG fprintf(af, "rstereoVotes: %d rmonoVotes: %d\n", rstereoVotes, rmonoVotes); #endif if (rstereoVotes > rmonoVotes) guessStereo = true; } #if RAW_GUESS_DEBUG if (guessStereo) fprintf(af, "stereo\n"); else fprintf(af, "mono\n"); #endif /* * Finally, determine the endianness and offset. * * Even MSB -> BigEndian or LittleEndian with Offset * Odd MSB -> LittleEndian or BigEndian with Offset */ guessBigEndian = evenMSB; guessOffset = 0; #if RAW_GUESS_DEBUG fprintf(af, "evenMSB: %d BE: %d\n", evenMSB, guessBigEndian); #endif for (test = 0; test < numTests; test++) { float former, latter; int i, offs; /* Extract a new array of the MSBs only: */ if (guessStereo) for (i = 0; i < (dataSize/4)-1; i++) rawData2[i] = rawData[test][4 * i + (evenMSB ? 0 : 1)]; else for (i = 0; i < (dataSize/2)-1; i++) rawData2[i] = rawData[test][2 * i + (evenMSB ? 0 : 1)]; former = 0.0; Extract(1, guessSigned, guessStereo, guessBigEndian, guessOffset, rawData[test], dataSize-4, data1, data2, &len1, &len2); offs=(!guessBigEndian); for(i=3; i<len1-4; i++) { if (rawData2[offs+i-2]==rawData2[offs+i-1] && rawData2[offs+i]==rawData2[offs+i-1]+1 && rawData2[offs+i]==rawData2[offs+i+1]) { former += data1[i]-data1[i-1]; } } latter = 0.0; Extract(1, guessSigned, guessStereo, !guessBigEndian, !guessOffset, rawData[test], dataSize, data1, data2, &len1, &len2); offs=(guessBigEndian); for(i=3; i<len1-4; i++) { if (rawData2[offs+i-2]==rawData2[offs+i-1] && rawData2[offs+i]==rawData2[offs+i-1]+1 && rawData2[offs+i]==rawData2[offs+i+1]) { latter += data1[i]-data1[i-1]; } } #if RAW_GUESS_DEBUG fprintf(af, "former: %f latter: %f\n", former, latter); #endif if (former <= latter) formerVotes++; else latterVotes++; } #if RAW_GUESS_DEBUG fprintf(af, "former (BE/LE): %d latter (LE+/BE+): %d\n", formerVotes, latterVotes); #endif // High barrier, since odd byte offsets are very rare if (latterVotes > formerVotes*2) { guessBigEndian = !guessBigEndian; guessOffset = !guessOffset; } #if RAW_GUESS_DEBUG if (guessBigEndian) fprintf(af, "big endian\n"); else fprintf(af, "little endian\n"); #endif #if RAW_GUESS_DEBUG if (guessOffset) fprintf(af, "offset 1 byte\n"); else fprintf(af, "no byte offset\n"); #endif format = SF_FORMAT_RAW | SF_FORMAT_PCM_16; if (guessBigEndian) format |= SF_ENDIAN_BIG; else format |= SF_ENDIAN_LITTLE; if (guessOffset) *out_offset = 1; if (guessStereo) *out_channels = 2; else *out_channels = 1; free(rawData2); return format;}int GuessIntFormats(int numTests, char **rawData, int dataSize, int *out_offset, int *out_channels){ int format = SF_FORMAT_RAW; bool guess16bit = false; bool evenMSB; float *data1 = (float *)malloc((dataSize + 4) * sizeof(float)); float *data2 = (float *)malloc((dataSize + 4) * sizeof(float)); int len1; int len2; int vote8 = 0; int vote16 = 0; int evenMSBVotes = 0; int oddMSBVotes = 0; int test; #if RAW_GUESS_DEBUG FILE *af = g_raw_debug_file; #endif *out_channels = 1; *out_offset = 0; /* * First test: we attempt to determine if the data is 8-bit or 16-bit. * We extract the odd and even bytes interpreted as signed-valued samples, * and compare their amplitude distributions. Noting that in 16-bit values, * the less significant 8 bits should have roughly flat distribution, while * the more significant 8 bits should have a tighter distribution, with a * smaller standard deviation. * * Note that this correctly makes the distinction whether we are dealing * with mono or stereo data. */ for (test = 0; test < numTests; test++) { float even, odd; Extract(0, 1, 1, 0, /* 8-bit signed stereo */ false, rawData[test], dataSize, data1, data2, &len1, &len2); even = AmpStat(data1, len1); odd = AmpStat(data2, len2); if ((even > 0.15) && (odd > 0.15)) { #if RAW_GUESS_DEBUG fprintf(af, "Both appear random: %.2f, %.2f.\n", even, odd); #endif } else if ((even > 0.15) || (odd > 0.15)) vote16++; else vote8++; /* Record which of the two was the MSB for future reference */ if (even < odd) evenMSBVotes++; else oddMSBVotes++; } evenMSB = (evenMSBVotes > oddMSBVotes); #if RAW_GUESS_DEBUG fprintf(af, "evenMSBVote: %d oddMSBVote: %d\n", evenMSBVotes, oddMSBVotes); fprintf(af, "vote8: %d vote16: %d\n", vote8, vote16); #endif if (vote8 > vote16) guess16bit = false; else guess16bit = true; if (!guess16bit) format = Guess8Bit(numTests, rawData, dataSize, out_channels); else format = Guess16Bit(numTests, rawData, dataSize, evenMSB, out_offset, out_channels); free(data1); free(data2); return format;}int RawAudioGuess(const wxString &in_fname, int *out_offset, int *out_channels){ const int numTests = 11; int headerSkipSize = 64; int dataSize = 16384; int format = SF_FORMAT_RAW; FILE *inf; int fileLen; char *rawData[numTests]; int test; #if RAW_GUESS_DEBUG FILE *af = fopen("raw.txt", "a"); g_raw_debug_file = af; fprintf(af, "File: %s\n", in_fname); #endif *out_offset = 0; *out_channels = 1; wxFFile in_wxFFile(FILENAME(in_fname).c_str(), wxT("rb")); if (!in_wxFFile.IsOpened()) return false; inf = in_wxFFile.fp(); if (!inf) { #if RAW_GUESS_DEBUG fclose(af); g_raw_debug_file = NULL; #endif return -1; } fseek(inf, 0, SEEK_END); fileLen = ftell(inf); if (fileLen < 8) return -1; if (fileLen < headerSkipSize) headerSkipSize = 0; if (fileLen < dataSize) dataSize = fileLen / 2; for (test = 0; test < numTests; test++) { int startPoint; rawData[test] = (char *)malloc(dataSize + 4); startPoint = (fileLen - dataSize) * (test + 1) / (numTests + 2); /* Make it a multiple of 16 (stereo double-precision) */ startPoint = (startPoint/16)*16; fseek(inf, headerSkipSize + startPoint, SEEK_SET); fread(rawData[test], 1, dataSize, inf); } in_wxFFile.Close(); /* * The floating-point tests will only return a valid format * if it's almost certainly floating-point data. On the other * hand, the integer tests will always return something, since * almost anything looks like it could be integer data... */ format = GuessFloatFormats(numTests, rawData, dataSize, out_offset, out_channels); if (format == 0) { format = GuessIntFormats(numTests, rawData, dataSize, out_offset, out_channels); } for (test = 0; test < numTests; test++) free(rawData[test]); #if RAW_GUESS_DEBUG fclose(af); g_raw_debug_file = NULL; #endif return format;}// Indentation settings for Vim and Emacs and unique identifier for Arch, a// version control system. Please do not modify past this point.//// Local Variables:// c-basic-offset: 3// indent-tabs-mode: nil// End://// vim: et sts=3 sw=3// arch-tag: 2011274b-10b7-4fce-b2f6-9f4cad4a69c2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -