OpenBve.Sounds.GetNormalizedMonoMix C# (CSharp) Méthode

GetNormalizedMonoMix() private static méthode

private static GetNormalizedMonoMix ( float samples ) : float[]
samples float
Résultat float[]
		private static float[] GetNormalizedMonoMix(float[][] samples) {
			/*
			 * This mixer tries to find silent channels and discards them.
			 * It then performs a mix to mono for all remaining channels
			 * and tries to detect destructive interference (in which case
			 * the first non-silent channel is returned). In all other cases,
			 * volume in the mono mix is normalized to the average volume
			 * in all non-silent channels. If necessary, the volume is
			 * further normalized to prevent overflow. This also prevents
			 * constructive interference.
			 * */
			// --- determine the volume per channel and the total volume ---
			float[] channelVolume = new float[samples.Length];
			float totalVolume = 0.0f;
			for (int i = 0; i < samples.Length; i++) {
				for (int j = 0; j < samples[i].Length; j++) {
					channelVolume[i] += Math.Abs(samples[i][j]);
				}
				channelVolume[i] /= samples[i].Length;
				totalVolume += channelVolume[i];
			}
			totalVolume /= samples.Length;
			// --- discard all channels that are below
			//     a certain threshold of the total volume ---
			const float silentThreshold = 0.05f;
			float[][] remainingSamples = new float[samples.Length][];
			int remainingSamplesUsed = 0;
			for (int i = 0; i < samples.Length; i++) {
			    if (!(channelVolume[i] > silentThreshold*totalVolume)) continue;
			    channelVolume[remainingSamplesUsed] = channelVolume[i];
			    remainingSamples[remainingSamplesUsed] = samples[i];
			    remainingSamplesUsed++;
			}
			switch (remainingSamplesUsed)
			{
			    case 1:
			        return remainingSamples[0];
			    case 0:
			        remainingSamples = samples;
			        remainingSamplesUsed = samples.Length;
			        break;
			    default:
			        totalVolume = 0.0f;
			        for (int i = 0; i < samples.Length; i++) {
			            totalVolume += channelVolume[i];
			        }
			        totalVolume /= remainingSamplesUsed;
			        break;
			}
			// --- produce a mono mix from all remaining channels ---
			float[] mix = new float[remainingSamples[0].Length];
			float mixVolume = 0.0f;
			for (int j = 0; j < remainingSamples[0].Length; j++) {
				for (int i = 0; i < remainingSamplesUsed; i++) {
					mix[j] += remainingSamples[i][j];
				}
				mix[j] /= remainingSamplesUsed;
				mixVolume += Math.Abs(mix[j]);
			}
			mixVolume /= remainingSamples[0].Length;
			// --- if the volume in the mono mix is below
			//     a certain threshold of the total volume,
			//     assume destructive interference and return
			//     the first non-silent channel ---
			const float destructiveInterferenceThreshold = 0.05f;
			if (mixVolume < destructiveInterferenceThreshold * totalVolume) {
				return remainingSamples[0];
			}
			// --- normalize the volume in the mono mix so that
			//     it corresponds to the average total volume ---
			float maximum = 0.0f;
			for (int j = 0; j < mix.Length; j++) {
				mix[j] *= totalVolume / mixVolume;
				float value = Math.Abs(mix[j]);
				if (value > maximum) maximum = value;
			}
			// --- if the maximum value now created exceeds the
			//     permissible range, normalize the mono mix further ---
			if (maximum > 1.0f) {
				for (int j = 0; j < mix.Length; j++) {
					mix[j] /= maximum;
				}
			}
			return mix;
		}