예제 #1
0
        public static Sound Read(Stream source)
        {
            BinaryReaderEx reader = new BinaryReaderEx(source);
            Sound result = new Sound();

            int id = reader.ReadInt32();
            if (id == 0x00394453)
            {
                int headerLength = reader.ReadInt32();
                int sampleLength = reader.ReadInt32();

                headerLength -= 12;
                if (headerLength > 0)
                    reader.ReadBytes(headerLength);

                byte[] wavData = reader.ReadBytes(sampleLength);
                using (MemoryStream wavDataMem = new MemoryStream(wavData))
                {
                    using (WaveStream wavStream = new WaveFileReader(wavDataMem))
                    {
                        byte[] rawWaveData = new byte[wavStream.Length];
                        wavStream.Read(rawWaveData, 0, (int)wavStream.Length);
                        result.SetSound(rawWaveData, wavStream.WaveFormat);
                    }
                }
            }

            return result;
        }
예제 #2
0
        public static void Process(Sound[] sounds, Chart[] charts)
        {
            List<int> keysoundsUsed = new List<int>();
            List<int> bgmKeysounds = new List<int>();

            foreach (Chart chart in charts)
            {
                foreach (Entry entry in chart.Entries)
                {
                    if (entry.Type == EntryType.Sample || entry.Type == EntryType.Marker)
                    {
                        if (entry.Value.Denominator == 1 && entry.Value.Numerator > 0)
                        {
                            int noteValue = (int)entry.Value.Numerator;
                            if (!keysoundsUsed.Contains(noteValue))
                            {
                                keysoundsUsed.Add(noteValue);
                                if (!bgmKeysounds.Contains(noteValue))
                                {
                                    bgmKeysounds.Add(noteValue);
                                }
                            }
                            if (entry.Player != 0)
                            {
                                bgmKeysounds.Remove(noteValue);
                            }
                        }
                    }
                }
            }

            int count = sounds.Length;
            for (int i = 0; i < count; i++)
            {
                for (int j = i + 1; j < count; j++)
                {
                    if (bgmKeysounds.Contains(i + 1) && bgmKeysounds.Contains(j + 1))
                    {
                        if (sounds[i].Data.Length == sounds[j].Data.Length && Math.Abs(sounds[i].Panning - sounds[j].Panning) == 1)
                        {
                            byte[] render0 = sounds[i].Render(1.0f);
                            byte[] render1 = sounds[j].Render(1.0f);
                            int renderLength = render0.Length;
                            byte[] output = new byte[renderLength];
                            for (int k = 0; k < renderLength; k++)
                            {
                                output[k] = (byte)(render0[k] | render1[k]);
                            }
                            sounds[i].SetSound(output, sounds[i].Format);
                            sounds[j].SetSound(new byte[] { }, sounds[j].Format);
                            sounds[i].Panning = 0.5f;
                            sounds[i].Volume = 1.0f;
                        }
                    }
                }
            }
        }
예제 #3
0
        public static Sound Read(Stream source)
        {
            Sound result = new Sound();
            BinaryReader reader = new BinaryReader(source);
            if (new string(reader.ReadChars(4)) == "2DX9")
            {
                int infoLength = reader.ReadInt32();
                int dataLength = reader.ReadInt32();
                reader.ReadInt16();
                int channel = reader.ReadInt16();
                int panning = reader.ReadInt16();
                int volume = reader.ReadInt16();
                int options = reader.ReadInt32();

                reader.ReadBytes(infoLength - 24);

                byte[] wavData = reader.ReadBytes(dataLength);
                using (MemoryStream wavDataMem = new MemoryStream(wavData))
                {
                    using (WaveStream wavStream = new WaveFileReader(wavDataMem))
                    {
                        int bytesToRead;

                        // using a mux, we force all sounds to be 2 channels
                        bytesToRead = (int)wavStream.Length;

                        byte[] rawWaveData = new byte[bytesToRead];
                        int bytesRead = wavStream.Read(rawWaveData, 0, bytesToRead);
                        result.SetSound(rawWaveData, wavStream.WaveFormat);

                        // calculate output panning
                        if (panning > 0x7F || panning < 0x01)
                            panning = 0x40;
                        result.Panning = ((float)panning - 1.0f) / 126.0f;

                        // calculate output volume
                        if (volume < 0x01)
                            volume = 0x01;
                        else if (volume > 0xFF)
                            volume = 0xFF;
                        result.Volume = VolumeTable[volume];

                        result.Channel = channel;
                    }
                }
            }

            return result;
        }
예제 #4
0
 public static Sound Read(Stream source)
 {
     Sound result = new Sound();
     WaveFileReader reader = new WaveFileReader(source);
     if (reader.Length > 0)
     {
         result.Data = new byte[reader.Length];
         reader.Read(result.Data, 0, result.Data.Length);
         result.Format = reader.WaveFormat;
     }
     else
     {
         result.Data = new byte[] { };
         result.Format = WaveFormat.CreateCustomFormat(WaveFormatEncoding.Pcm, 44100, 2, 44100 * 4, 4, 16);
     }
     result.Panning = 0.5f;
     result.Volume = 1.0f;
     return result;
 }
예제 #5
0
        public static Sound Read(Stream source, Properties properties)
        {
            BinaryReaderEx reader = new BinaryReaderEx(source);
            Sound result = new Sound();
            bool stereo = (properties.Flag0F & 0x80) != 0;
            byte[] data = reader.ReadBytes(properties.SampleLength);
            int dataLength = data.Length;
            byte[] newData = new byte[dataLength * (stereo ? 1 : 2)];

            // translate the "signed" data
            int newDataPtr = 0;
            for (int i = 0; i < dataLength; i += 2)
            {
                int sample = ((int)data[i] << 8) | data[i + 1];
                if (sample >= 0x8000)
                {
                    sample = -(sample & 0x7FFF);
                }
                newData[newDataPtr] = (byte)(sample & 0xFF);
                newData[newDataPtr + 1] = (byte)((sample >> 8) & 0xFF);
                if (!stereo)
                {
                    newData[newDataPtr + 2] = newData[newDataPtr];
                    newData[newDataPtr + 3] = newData[newDataPtr + 1];
                    newDataPtr += 2;
                }
                newDataPtr += 2;
            }

            // 16-bit stereo format
            result.Format = WaveFormat.CreateCustomFormat(WaveFormatEncoding.Pcm, properties.Frequency, 2, properties.Frequency * 4, 4, 16);
            result.Data = newData;

            // determine volume
            result.Volume = VolumeTable[properties.Volume];

            // determine panning
            result.Panning = (float)(properties.Panning - 1) / (float)0x7E;

            // return the final result
            return result;
        }
예제 #6
0
        // note: I/O functions do not use the Offset field in Properties
        public static Sound Read(Stream source, Properties prop)
        {
            Sound result = new Sound();
            byte[] data = ReadRaw(source, prop);

            // get the true sample rate
            int sampleRate = prop.Frequency;
            sampleRate = (int)((sampleRate * 44100L) / 60216L);

            // decode the sound and quantize to 16 bits stereo
            switch (prop.SampleType & 0xC)
            {
                case 0x0:
                    data = Decode8(data);
                    break;
                case 0x4:
                    data = Decode16(data);
                    break;
                case 0x8:
                    data = Decode4(data);
                    break;
            }

            // 16-bit stereo format
            result.Format = WaveFormat.CreateCustomFormat(WaveFormatEncoding.Pcm, sampleRate, 2, sampleRate * 4, 4, 16);
            result.Data = data;

            // determine volume
            result.Volume = VolumeTable[prop.Volume];

            // determine panning
            int panValue = prop.Panning & 0xF;
            if (panValue < 1)
                panValue = 8;
            if (panValue > 15)
                panValue = 8;
            result.Panning = (float)(panValue - 1) / 14f;

            // return the final result
            return result;
        }
예제 #7
0
        public static byte[] Render(Chart chart, Sound[] sounds)
        {
            Dictionary<long, Entry> lastNote = new Dictionary<long, Entry>();
            Dictionary<int, Fraction> noteCutoff = new Dictionary<int, Fraction>();
            Dictionary<int, byte[]> renderedSamples = new Dictionary<int, byte[]>();

            int[] buffer = new int[0];

            chart.Entries.Reverse();

            foreach (Entry entry in chart.Entries)
            {
                if (entry.Type == EntryType.Sample)
                {
                    lastNote[GetIdentifier(entry)] = entry;
                }
                else if (entry.Type == EntryType.Marker)
                {
                    Sound sound;

                    if (entry.Value.Numerator > 0)
                    {
                        byte[] soundData = null;
                        int soundIndex = (int)entry.Value - 1;
                        sound = sounds[(int)entry.Value - 1];

                        if (renderedSamples.ContainsKey(soundIndex))
                        {
                            soundData = renderedSamples[soundIndex];
                        }
                        else if (sound != null)
                        {
                            soundData = sound.Render(1.0f);
                            renderedSamples[soundIndex] = soundData;
                        }

                        Fraction cutoff = new Fraction(-1, 1);
                        if (sound.Channel >= 0 && noteCutoff.ContainsKey(sound.Channel))
                        {
                            cutoff = noteCutoff[sound.Channel];
                        }
                        if (soundData != null)
                        {
                            Paste(soundData, ref buffer, entry.LinearOffset * chart.TickRate, cutoff * chart.TickRate);
                        }
                        if (sound.Channel >= 0)
                            noteCutoff[sound.Channel] = entry.LinearOffset;
                    }
                }
            }

            chart.Entries.Reverse();

            int length = buffer.Length;
            Int16[] outputSamples = new Int16[length];
            int normalization = 1;

            for (int i = 0; i < length; i++)
            {
                // auto-normalize
                int currentSample = buffer[i] / normalization;
                while (currentSample > 32767 || currentSample < -32768)
                {
                    normalization++;
                    currentSample = buffer[i] / normalization;
                }
            }

            for (int i = 0; i < length; i++)
            {
                outputSamples[i] = (Int16)(buffer[i] / normalization);
            }

            using (MemoryStream mem = new MemoryStream())
            {
                using (WaveFileWriter writer = new WaveFileWriter(new IgnoreDisposeStream(mem), WaveFormat.CreateCustomFormat(WaveFormatEncoding.Pcm, 44100, 2, 44100 * 4, 4, 16)))
                {
                    writer.WriteSamples(outputSamples, 0, length);
                }
                mem.Flush();
                return mem.ToArray();
            }
        }
예제 #8
0
        public static MicrosoftXWB Read(Stream source)
        {
            MicrosoftXWB result = new MicrosoftXWB();
            using (BinaryReader reader = new BinaryReader(source))
            {
                int sampleCount = 0;
                WaveBankHeader header = new WaveBankHeader();
                WaveBankData bank = new WaveBankData();
                WaveBankEntry[] entries = { };
                string[] names = { };
                MemoryStream dataChunk = new MemoryStream();

                header = WaveBankHeader.Read(source);

                for (int i = 0; i < (int)WaveBankSegIdx.Count; i++)
                {
                    WaveBankRegion region = header.Segments[i];
                    if (region.Length > 0)
                    {
                        source.Position = region.Offset;
                        MemoryStream mem = new MemoryStream(reader.ReadBytes(region.Length));
                        BinaryReader memReader = new BinaryReader(mem);
                        switch (i)
                        {
                            case (int)WaveBankSegIdx.BankData:
                                bank = WaveBankData.Read(mem);
                                sampleCount = bank.EntryCount;
                                entries = new WaveBankEntry[sampleCount];
                                names = new string[sampleCount];
                                mem.Dispose();
                                break;
                            case (int)WaveBankSegIdx.EntryMetaData:
                                for (int j = 0; j < sampleCount; j++)
                                    entries[j] = WaveBankEntry.Read(mem);
                                mem.Dispose();
                                break;
                            case (int)WaveBankSegIdx.EntryNames:
                                for (int j = 0; j < sampleCount; j++)
                                    names[j] = Util.TrimNulls(new string(memReader.ReadChars(Constants.WavebankEntrynameLength)));
                                mem.Dispose();
                                break;
                            case (int)WaveBankSegIdx.EntryWaveData:
                                dataChunk = mem;
                                break;
                            case (int)WaveBankSegIdx.SeekTables:
                                mem.Dispose();
                                break;
                            default:
                                mem.Dispose();
                                break;
                        }
                    }
                }

                if (sampleCount > 0)
                {
                    List<Sound> sounds = new List<Sound>();
                    for (int i = 0; i < sampleCount; i++)
                    {
                        WaveBankEntry entry = entries[i];
                        byte[] rawData = new byte[entry.PlayRegion.Length];
                        dataChunk.Position = entry.PlayRegion.Offset;
                        dataChunk.Read(rawData, 0, rawData.Length);

                        WaveFormat dataFormat;
                        switch (entry.Format.FormatTag)
                        {
                            case Constants.WavebankminiformatTagPcm:
                                dataFormat = WaveFormat.CreateCustomFormat(WaveFormatEncoding.Pcm, entry.Format.SamplesPerSec, entry.Format.Channels, entry.Format.AvgBytesPerSec, entry.Format.BlockAlign, entry.Format.BitsPerSample);
                                break;
                            case Constants.WavebankminiformatTagXma:
                                dataFormat = WaveFormat.CreateCustomFormat(WaveFormatEncoding.DviAdpcm, entry.Format.SamplesPerSec, entry.Format.Channels, entry.Format.AvgBytesPerSec, entry.Format.BlockAlign, entry.Format.BitsPerSample);
                                break;
                            case Constants.WavebankminiformatTagAdpcm:
                                dataFormat = new AdpcmWaveFormat(entry.Format.SamplesPerSec, entry.Format.Channels, (short)entry.Format.BlockAlign, entry.Format.AvgBytesPerSec, (short)entry.Format.AdpcmSamplesPerBlock);
                                //dataFormat = WaveFormat.CreateCustomFormat(WaveFormatEncoding.Adpcm, entry.Format.SamplesPerSec, entry.Format.Channels, entry.Format.AvgBytesPerSec, entry.Format.BlockAlign, entry.Format.BitsPerSample);
                                break;
                            case Constants.WavebankminiformatTagWma:
                                dataFormat = WaveFormat.CreateCustomFormat(WaveFormatEncoding.WindowsMediaAudio, entry.Format.SamplesPerSec, entry.Format.Channels, entry.Format.AvgBytesPerSec, entry.Format.BlockAlign, entry.Format.BitsPerSample);
                                break;
                            default:
                                dataFormat = null;
                                break;
                        }

                        if (dataFormat != null)
                        {
                            Sound baseSound = new Sound(rawData, dataFormat);
                            baseSound.Name = names[i];
                            sounds.Add(baseSound);
                        }
                    }
                    result.sounds = sounds.ToArray();
                    result.Name = bank.BankName;
                }
            }
            return result;
        }
예제 #9
0
 // returns the number of bytes written
 public static int Write(Sound source, Stream target, Properties prop)
 {
     BinaryWriterEx writer = new BinaryWriterEx(target);
     return 0;
 }
예제 #10
0
        public static void ConvertSounds(Sound[] sounds, string filename, float volume)
        {
            string name = Path.GetFileNameWithoutExtension(Path.GetFileName(filename));
            string targetPath = Path.Combine(Path.GetDirectoryName(filename), name);

            if (!Directory.Exists(targetPath))
                Directory.CreateDirectory(targetPath);

            int count = sounds.Length;

            for (int j = 0; j < count; j++)
            {
                int sampleIndex = j + 1;
                sounds[j].WriteFile(Path.Combine(targetPath, Scharfrichter.Codec.Util.ConvertToBMEString(sampleIndex, 4) + @".wav"), volume);
            }
        }