/// <summary> /// Mix Sound sample of given <see cref="Chart"/>. /// Resulting a single <see cref="MixedSample"/> of prerendered the <see cref="Chart"/>. /// </summary> /// <param name="chart">a <see cref="Chart"/> instance that contain samples to be mixed and prerendered.</param> /// <param name="mode">Specifies sample mixing mode.</param> /// <param name="channelCount">The number of channels that will be used for prerendering the <see cref="Chart"/>.</param> /// <param name="sampleRate">The rate of sample that will be used for prerendering the <see cref="Chart"/>.</param> /// <returns>a Single <see cref="MixedSample"/> of prerendered given <see cref="Chart"/></returns> public static MixedSample Mix(Chart chart, MixMode mode = MixMode.Full, int channelCount = 2, int sampleRate = 44100) { int sampleCount = (sampleRate * channelCount); var samples = new short[sampleCount * (int)chart.Duration.TotalSeconds]; var events = Array.ConvertAll(Array.FindAll(chart.Events, (ev) => ev is Event.Sound), ((ev) => ev as Event.Sound)); foreach (var ev in events) { if (ev.Payload == null || ev.Signature == Event.SignatureType.Release || (mode == MixMode.BGM && ev.Channel != Event.ChannelType.BGM) || (mode == MixMode.Keysound && ev.Channel == Event.ChannelType.BGM)) { continue; } using (var stream = new MemoryStream(ev.Payload)) using (var decoder = SoundProcessorFactory.CreateDecoder(stream)) { var info = decoder.SampleInfo; var keysound = new short[info.SampleCount]; long offset = (long)(ev.Timestamp.TotalSeconds * sampleCount); long read = 0; while ((read = decoder.Read(keysound, info.SampleCount)) > 0) { if (offset + read >= samples.Length) { int newSize = samples.Length; while (newSize < offset + read) { newSize += sampleRate * channelCount; } Array.Resize(ref samples, newSize); } for (int i = 0; i < read; i++) { int buffer = samples[offset + i] + keysound[i]; if (buffer > short.MaxValue) { buffer = short.MaxValue; } else if (buffer < short.MinValue) { buffer = short.MinValue; } samples[offset + i] = (short)buffer; } offset += read; } } } return(new MixedSample(samples, channelCount, sampleRate)); }
public MainForm() { try { // Costura load assembly on demand (lazy load) // So we initialize this earlier to prevent heavy load when we initialize first chart InitializeComponent(); SoundSystem.Instance.Initialize(); SoundProcessorFactory.InstallEncoder <MP3Encoder>((stream, sampleRate, channel, own) => new MP3Encoder(stream, sampleRate, channel, own)); } catch (Exception ex) { MessageBox.Show("Failed to initialize sound system.\nPlease make sure OpenAL is placed / installed properly or rerun the application once more.\n\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); Application.Exit(); return; } }
private static SampleInfo EncodeTo <T>(byte[] payload) where T : SoundEncoder { payload = payload == null ? new byte[0] : payload; if (payload == null || payload.Length == 0) { return(default(SampleInfo)); } using (var decoder = SoundProcessorFactory.CreateDecoder(new MemoryStream(payload))) { if (decoder == null) { return(default(SampleInfo)); } else if (!(decoder is T)) { short[] buffer = new short[44100 * 2]; using (var sampleStream = new MemoryStream()) using (var encoder = SoundProcessorFactory.CreateEncoder <T>(sampleStream, 44100, 2)) { long read = 0; do { read = decoder.Read(buffer, buffer.Length); encoder.Write(buffer, read); }while (read > 0); encoder.Flush(); payload = sampleStream.ToArray(); return(encoder.SampleInfo); } } return(decoder.SampleInfo); } }