void BwDoWork(object sender, DoWorkEventArgs e)
        {
            var args = e.Argument as BackgroundWorkerArgs;

            e.Result = args;

            short nCh         = 1;
            int   sampleFreq  = 44100;
            int   sineFreq    = sampleFreq / 4;
            long  nPeriod     = (long)(args.durationSec * sineFreq);
            long  nFrames     = nPeriod * 4;
            long  nFrameBytes = nFrames * nCh * 4; // 8==sizeof float

            if (0x7fff0000 < nFrameBytes)
            {
                args.errMsg = "Error: Sound Duration is too long!";
            }

            try {
                using (var bw = new BinaryWriter(File.Open(args.path, FileMode.Create))) {
                    var wwl           = new WavWriterLowLevel();
                    int dataChunkSize = (int)(nFrameBytes);
                    int riffChunkSize = 4    /* RIFF */
                                        + 26 /* fmt */
                                        + 8  /* DATA */
                                        + dataChunkSize;

                    wwl.RiffChunkWrite(bw, riffChunkSize);
                    wwl.FmtChunkWriteEx(bw, nCh, sampleFreq, 32, WavWriterLowLevel.WAVE_FORMAT_IEEE_FLOAT, 0);
                    wwl.DataChunkHeaderWrite(bw, dataChunkSize);
                    for (int i = 0; i < nPeriod; ++i)
                    {
                        var signal = new float[] {
                            0.0f,
                            +(float)Math.Pow(10, args.magnitude / 20.0),
                            0.0f,
                            -(float)Math.Pow(10, args.magnitude / 20.0),
                        };
                        bw.Write(signal[0]);
                        bw.Write(signal[1]);
                        bw.Write(signal[2]);
                        bw.Write(signal[3]);
                    }
                }
            } catch (System.Exception ex) {
                args.errMsg = ex.ToString();
            }
            args.errMsg = "";
        }
Beispiel #2
0
        public static bool WriteWav(BinaryWriter bw, PcmData pcm, List <WavChunkParams> wavParamList)
        {
            var writer = new WavWriterLowLevel();

            bool isDs64  = wavParamList.Find((WavChunkParams p) => { return(p.ChunkType == WavChunkType.DS64); }) != null;
            long posDS64 = -1;
            long posRiff = -1;



            foreach (var i in wavParamList)
            {
                switch (i.ChunkType)
                {
                case WavChunkType.RIFF: {
                    // 仮。ファイルサイズが決まった時に書き直す。
                    posRiff = bw.BaseStream.Position;
                    writer.RiffChunkWrite(bw, -1);
                }
                break;

                case WavChunkType.fmt: {
                    var fmt = i as FmtChunkParams;
                    switch (fmt.StructType)
                    {
                    case FmtChunkParams.WaveFormatStructType.WaveFormat:
                        writer.FmtChunkWrite(bw, (short)pcm.NumChannels, (int)pcm.SampleRate, (short)pcm.BitsPerSample);
                        break;

                    case FmtChunkParams.WaveFormatStructType.WaveFormatEx:
                        writer.FmtChunkWriteEx(bw, (short)pcm.NumChannels, (int)pcm.SampleRate,
                                               (short)pcm.BitsPerSample,
                                               pcm.SampleValueRepresentationType == PcmData.ValueRepresentationType.SFloat ? WavWriterLowLevel.WAVE_FORMAT_IEEE_FLOAT : WavWriterLowLevel.WAVE_FORMAT_PCM,
                                               (short)fmt.CbSize);
                        break;

                    case FmtChunkParams.WaveFormatStructType.WaveFormatExtensible: {
                        int dwChannelMask = 0;
                        if (pcm.NumChannels == 2)
                        {
                            dwChannelMask = 3;
                        }

                        writer.FmtChunkWriteExtensible(bw, (short)pcm.NumChannels, (int)pcm.SampleRate,
                                                       (short)pcm.BitsPerSample, (short)pcm.ValidBitsPerSample,
                                                       pcm.SampleValueRepresentationType, (int)dwChannelMask);
                    }
                    break;

                    default:
                        System.Diagnostics.Debug.Assert(false);
                        break;
                    }
                }
                break;

                case WavChunkType.DATA: {
                    var  data         = i as DataChunkParams;
                    long posDataStart = bw.BaseStream.Position;

                    writer.DataChunkWrite(bw, isDs64, pcm.GetSampleArray());
                    if (!isDs64 && 0 < data.ExtraChunkBytes)
                    {
                        // 実際よりも長いチャンクサイズを書き込む。

                        long posDataEnd = bw.BaseStream.Position;

                        bw.BaseStream.Seek(posDataStart + 4, SeekOrigin.Begin);
                        int chunkSize = pcm.GetSampleArray().Length + data.ExtraChunkBytes;
                        bw.Write(chunkSize);

                        bw.BaseStream.Seek(posDataEnd, SeekOrigin.Begin);
                    }
                }
                break;

                case WavChunkType.JUNK: {
                    var junk = i as JunkChunkParams;
                    writer.JunkChunkWrite(bw, (ushort)junk.ContentBytes);
                }
                break;

                case WavChunkType.bext: {
                    var bext = i as BextChunkParams;
                    writer.BextChunkWrite(bw, bext.Description, bext.Originator, bext.OriginatorReference,
                                          bext.OriginationDate, bext.OriginationTime, bext.TimeReference, null, 0,
                                          0, 0, 0, 0, null);
                }
                break;

                case WavChunkType.DS64: {
                    posDS64 = bw.BaseStream.Position;
                    var ds64 = i as DS64ChunkParams;
                    writer.Ds64ChunkWrite(bw, ds64.RiffSize, ds64.DataSize, ds64.SampleCount);
                }
                break;

                case WavChunkType.ID3: {
                    var id3 = i as ID3ChunkParams;
                    writer.ID3ChunkWrite(bw, id3.Title, id3.Album, id3.Artists, id3.AlbumCoverArt, id3.AlbumCoverArtMimeType);
                }
                break;
                }
            }

            long posEnd = bw.BaseStream.Position;

            RiffChunkParams riff = wavParamList.Find((WavChunkParams p) => { return(p.ChunkType == WavChunkType.RIFF); }) as RiffChunkParams;

            if (!isDs64)
            {
                // RIFFのサイズが決まったので書き込む
                int riffSize = (int)(posEnd - posRiff - 8);
                riffSize += riff.ExtraChunkBytes;

                bw.BaseStream.Seek(posRiff, SeekOrigin.Begin);
                writer.RiffChunkWrite(bw, riffSize);
                bw.BaseStream.Seek(posEnd, SeekOrigin.Begin);
            }
            else
            {
                // DS64のサイズが決まったので書き込む
                DataChunkParams dcp = wavParamList.Find((WavChunkParams p) => { return(p.ChunkType == WavChunkType.DATA); }) as DataChunkParams;

                long riffSize = posEnd - posRiff - 8;
                riffSize += riff.ExtraChunkBytes;

                long dataSize = pcm.GetSampleArray().LongLength;
                if (0 < dcp.ExtraChunkBytes)
                {
                    dataSize += dcp.ExtraChunkBytes;
                }

                long sampleCount = pcm.NumFrames;

                bw.BaseStream.Seek(posDS64, SeekOrigin.Begin);
                writer.Ds64ChunkWrite(bw, riffSize, dataSize, sampleCount);
                bw.BaseStream.Seek(posEnd, SeekOrigin.Begin);
            }

            if (0 < riff.GarbageBytes)
            {
                // ファイルの最後にごみを書き込む
                var zeroes = new byte[riff.GarbageBytes];
                bw.Write(zeroes);
            }

            return(true);
        }