Files
cuetools.net/CUETools.TestHelpers/NoiseAndErrorsGenerator.cs

127 lines
3.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using CUETools.Codecs;
namespace CUETools.TestHelpers
{
public class NoiseAndErrorsGenerator : IAudioSource
{
private long _sampleOffset, _sampleCount;
private AudioPCMConfig pcm;
private Random rnd, rnd2;
private byte[] temp;
private int[] errors;
private int tempOffs;
private int nextError;
public NoiseAndErrorsGenerator(AudioPCMConfig pcm, long sampleCount, int seed, int offset, int errors, int maxStrideErrors = 0)
{
if (offset < 0)
throw new ArgumentOutOfRangeException("offset", "offset cannot be negative");
if (errors < 0)
throw new ArgumentOutOfRangeException("offset", "errors cannot be negative");
this._sampleOffset = 0;
this._sampleCount = sampleCount;
this.pcm = pcm;
this.rnd = new Random(seed);
this.temp = new byte[8192 * pcm.BlockAlign];
this.tempOffs = temp.Length;
int byteOff = offset * pcm.BlockAlign;
for (int k = 0; k < byteOff / temp.Length; k++)
rnd.NextBytes(temp);
if (byteOff % temp.Length > 0)
rnd.NextBytes(new byte[byteOff % temp.Length]);
this.errors = new int[errors];
this.rnd2 = new Random(seed);
var strideErrors = new int[10 * 588];
for (int i = 0; i < errors; i++)
{
do
{
this.errors[i] = this.rnd2.Next(0, (int)sampleCount);
} while (maxStrideErrors > 0 && strideErrors[this.errors[i] % (10 * 588)] >= maxStrideErrors);
strideErrors[this.errors[i] % (10 * 588)]++;
}
this.rnd2 = new Random(seed);
Array.Sort(this.errors);
this.nextError = 0;
}
public IAudioDecoderSettings Settings => null;
public NoiseAndErrorsGenerator(long sampleCount)
: this(AudioPCMConfig.RedBook, sampleCount, 0, 0, 0)
{
}
public TimeSpan Duration => Length < 0 ? TimeSpan.Zero : TimeSpan.FromSeconds((double)Length / PCM.SampleRate);
public long Length
{
get
{
return _sampleCount;
}
}
public long Remaining
{
get
{
return _sampleCount - _sampleOffset;
}
}
public long Position
{
get
{
return _sampleOffset;
}
set
{
_sampleOffset = value;
}
}
public AudioPCMConfig PCM { get { return pcm; } }
public int Read(AudioBuffer buff, int maxLength)
{
buff.Prepare(this, maxLength);
int buffOffs = 0;
while (buffOffs < buff.ByteLength)
{
if (tempOffs == temp.Length)
{
rnd.NextBytes(temp);
tempOffs = 0;
}
int chunk = Math.Min(buff.ByteLength - buffOffs, temp.Length - tempOffs);
Array.Copy(temp, tempOffs, buff.Bytes, buffOffs, chunk);
buffOffs += chunk;
tempOffs += chunk;
}
while (this.nextError < this.errors.Length && this.errors[this.nextError] < _sampleOffset + buff.Length)
{
for (int i = 0; i < PCM.BlockAlign; i++)
buff.Bytes[(this.errors[this.nextError] - _sampleOffset) * PCM.BlockAlign + i] ^= (byte)this.rnd2.Next(1, 255);
this.nextError++;
}
_sampleOffset += buff.Length;
return buff.Length;
}
public void Close()
{
}
public string Path { get { return null; } }
}
}