-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit f2ed2ca
Showing
78 changed files
with
4,299 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# User-specific files | ||
*.suo | ||
*.user | ||
|
||
# Build results | ||
bin/ | ||
packages/ | ||
obj/ | ||
**/StyleCop.Cache | ||
|
||
# Profiling results | ||
*.vsp | ||
*.vspx | ||
|
||
# Timelapse output | ||
Backups/ | ||
|
||
# Visual Studio 2015 cache/options directory | ||
.vs/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
# Visual Studio 14 | ||
VisualStudioVersion = 14.0.25420.1 | ||
MinimumVisualStudioVersion = 10.0.40219.1 | ||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CrossTimeDsp", "CrossTimeDsp\CrossTimeDsp.csproj", "{2ACACAAF-DE8F-4637-AD15-A59EDE5EA107}" | ||
EndProject | ||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\UnitTests.csproj", "{1C7DC7A2-ADCB-46F8-AF31-F2569B9F769F}" | ||
EndProject | ||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{96AE086E-E31E-47F1-BC86-FFE29D2AADDB}" | ||
ProjectSection(SolutionItems) = preProject | ||
.gitignore = .gitignore | ||
LICENSE.md = LICENSE.md | ||
README.md = README.md | ||
EndProjectSection | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|Any CPU = Debug|Any CPU | ||
Release|Any CPU = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{2ACACAAF-DE8F-4637-AD15-A59EDE5EA107}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{2ACACAAF-DE8F-4637-AD15-A59EDE5EA107}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{2ACACAAF-DE8F-4637-AD15-A59EDE5EA107}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{2ACACAAF-DE8F-4637-AD15-A59EDE5EA107}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{1C7DC7A2-ADCB-46F8-AF31-F2569B9F769F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{1C7DC7A2-ADCB-46F8-AF31-F2569B9F769F}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{1C7DC7A2-ADCB-46F8-AF31-F2569B9F769F}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{1C7DC7A2-ADCB-46F8-AF31-F2569B9F769F}.Release|Any CPU.Build.0 = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(SolutionProperties) = preSolution | ||
HideSolutionNode = FALSE | ||
EndGlobalSection | ||
GlobalSection(TeamFoundationVersionControl) = preSolution | ||
SccNumberOfProjects = 3 | ||
SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C} | ||
SccTeamFoundationServer = https://tfs.codeplex.com/tfs/tfs35 | ||
SccLocalPath0 = . | ||
SccProjectUniqueName1 = CrossTimeDsp\\CrossTimeDsp.csproj | ||
SccProjectName1 = CrossTimeDsp | ||
SccLocalPath1 = CrossTimeDsp | ||
SccProjectUniqueName2 = UnitTests\\UnitTests.csproj | ||
SccProjectName2 = UnitTests | ||
SccLocalPath2 = UnitTests | ||
EndGlobalSection | ||
EndGlobal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<configuration> | ||
<!-- Register a config section for Cross Time DSP as its config is more complex than the key/value pairs supported by app settings. | ||
As normal for XML, all content is case sensitive. | ||
--> | ||
<configSections> | ||
<section name="crossTimeDsp" type="CrossTimeDsp.Configuration.XmlConfigurationHandler`1[[CrossTimeDsp.Configuration.CrossTimeDspSection, CrossTimeDsp]], CrossTimeDsp"/> | ||
</configSections> | ||
<crossTimeDsp> | ||
<!-- The engine element controls how Cross Time DSP performs signal processing. --> | ||
<!-- The precision element specifies what form of math Cross Time DSP uses when performing DSP operations. | ||
Supported values are Double, Q31, Q31_32x64, and Q31Adaptive. | ||
- Specifying Double causes Cross Time DSP to use 64 bit floating point numbers for all its calculations. This is generally | ||
considered to be mastering quality. | ||
- Specifying Q31 results in 32 bit fixed point math being used with 64 bit accumulators. Accuracy varies depending on the | ||
filters specified. If the signal to be processed uses the full bit depth available in the input file's format this typically | ||
produces around 23.5 bits of signal for filters centered at normalized frequencies of 0.05 or higher, degrading to 16 bits of | ||
signal as the center frequency is reduced to a normalized frequency of 0.001. | ||
- Specifying Q31_32x64 results in 32 bit fixed point math being used with 64 bit accumulators and 64 bit feedback state variables. | ||
The increased feedback precision improves accuracy by about three bits relative to the Q31 setting. | ||
- Specifying Q31_62x64 results in 32 bit fixed point math being used with 64 bit accumulators, coefficients, and feedback state | ||
variables. The increased coefficient precision improves accuracy by about five bits relative to the Q31_32x64 setting. | ||
- Specifiying Q31Adaptive causes Cross Time DSP to use Q31 precision for filters centered above the normalized frequency | ||
specified by the q31_32x64_Threshold attribute and Q31_32x64 for filters centered at lower frequencies. Filters centered below | ||
q31_64x64_Threshold use Q31_64x64 precision. These two thresholds allow tuning of filter banks' accuracy versus processing | ||
requirements. | ||
In memory processing using doubles is around 40% faster than fixed point and maintains higher precision. Use of doubles is | ||
therefore recommended as a default. The Q31 forms can be faster on long tracks since they have half the in memory footprint and | ||
may therefore avoid swapping of the reverse time buffer to disk that would occur with doubles. But the primary reason Cross Time | ||
DSP supports fixed point is to allow evaluation of fixed point accuracy relative to doubles when porting filters to processors | ||
lacking 64 bit floating point support. | ||
--> | ||
<!-- The reverseTimeAntiClippingAttenuationInDB attribute specifies how to change the volume between the input and output files. | ||
By default most audio processors, Cross Time DSP included, scale their input to match their output so that the output plays back at | ||
the same loudness. Reverse time processing typically increases peak amplitudes by 6 to 10dB, making it desirable to attenuate the | ||
output by a similar factor to avoid clipping. More sophisticated approaches to managing the tradeoff between playback loudness and | ||
clipping exist with ReplayGain enjoying wide support. The intent here is simply to ensure Cross Time DSP's output files have no | ||
more clipping than the input files do. The output file's replay gain can be computed separately if desired. | ||
If filters with gain are included in the filter bank additional margin may be required to avoid clipping; how much depends on the | ||
music's power spectral density and the bandwidth over which the filter operates. Conversely, with attenuating filters it may be | ||
desirable to reduce margin. | ||
The reverseTimeAntiClippingAttenuationInDB parameter is ignored if no reverse time filters are specified. Attenuation is not | ||
currently supported in a forward time only configuration. | ||
--> | ||
<engine precision="Double" reverseTimeAntiClippingAttenuationInDB="-10"> | ||
<!-- The q32Adaptive element specifies the normalized frequencies below which Q31 precision increases to Q31_32x64 and Q31_32x64 | ||
precision increases to Q31_64x64. | ||
See remarks for the Q31Adaptive filter precision above for details. | ||
--> | ||
<q31Adaptive q31_32x64_Threshold="0.02" q31_64x64_Threshold="0.002"/> | ||
</engine> | ||
<!-- The filters element specifies the filtering Cross Time DSP should perform. Filters are applied in the order specified. --> | ||
<filters> | ||
<!-- A firstOrderFilterElement specifies a single first order to include in Cross Time DSP's processing chain. The syntax is | ||
<firstOrder timeDirection="<direction>" type="<type>" f0="<center frequency in Hz>" /> | ||
where | ||
- the direction attribute specifies whether the filter operates in forward or reverse time | ||
valid values are Forward and Reverse | ||
- the type attribute specifies the type of the filter | ||
valid values are Allpass | ||
- f0 is the filter's center frequency in Hz | ||
--> | ||
<!-- A biquad specifies a single biquad to include in Cross Time DSP's processing chain. The syntax is | ||
<biquad timeDirection="<direction>" type="<type>" f0="<center frequency in Hz>" q="" gainInDB="" /> | ||
where | ||
- the direction attribute specifies whether the filter operates in forward or reverse time | ||
Valid values are Forward and Reverse. | ||
- the type attribute specifies the type of the filter | ||
Valid values are Allpass, Bandpass, Highpass, HighShelf, Lowpass, LowShelf, Notch, and Peaking. | ||
- f0 is the filter's center frequency in Hz | ||
- q is the filter's Q as defined in the Bristow-Johnson cookbok | ||
- gainInDB is the gain of shelving and peaking filters | ||
This attribute is ignored by other filter types. | ||
--> | ||
<!-- The example below has the following phase corrections. | ||
- a first order allpass correction at 40Hz to compensate for second order woofer rolloff in the low bass | ||
- a LR4 phase correction at 150Hz to compensate for dipole equalization of a midrange | ||
- a LR6 correction at 200Hz to linearize an LR6 crossover at this frequency | ||
- a LR6 correction at 1.7kHz to linearize an LR6 crossover at this frequency | ||
--> | ||
<firstOrder timeDirection="Reverse" type="Allpass" f0="40"/> | ||
<biquad timeDirection="Reverse" type="Allpass" f0="150" q="0.7071"/> | ||
<biquad timeDirection="Reverse" type="Allpass" f0="200" q="1.0"/> | ||
<firstOrder timeDirection="Reverse" type="Allpass" f0="200"/> | ||
<biquad timeDirection="Reverse" type="Allpass" f0="1700" q="1.0"/> | ||
<firstOrder timeDirection="Reverse" type="Allpass" f0="1700"/> | ||
</filters> | ||
<!-- The output section provides some control over how Cross Time DSP writes output files to disk. --> | ||
<!-- The encoding attribute specifies the format of the output file. | ||
Supported values are Wav and Flac. | ||
--> | ||
<output encoding="Flac"> | ||
<!-- The collidingFileNamePostfix element specifies the string to append to file names when Cross Time DSP is processing a | ||
file, the input and output directories are the same, and the output format is the same as the imput format. This is needed to | ||
keep to the input and output files distinct in this special case. In other situations the input and output directories or | ||
formats differ and the output file name is kept the same as the input file. Regardless of what the output file name ends up being, existing files will be overwritten if they are older | ||
than the input file. Output files which are newer than the input file are assumed to be up to date and are not modified. If this | ||
assumption is incorrect, delete the output file and rerun Cross Time DSP. | ||
In the case where some files have been converted between formats and the directory is being reprocessed, set this element to | ||
<collidingFileNamePostfix></collidingFileNamePostfix> to avoid generating duplicates of the existing files. | ||
The output file extension is updated as needed to reflect its encoding. | ||
--> | ||
<collidingFileNamePostfix> - Cross Time DSP</collidingFileNamePostfix> | ||
<!-- The flac element specifies options for FLAC files. It is ignored when the output encoding is not FLAC. | ||
--> | ||
<!-- The bitsPerSample attribute specifies the bit depth of the output FLAC file. | ||
See remarks for the wav element's bitsPerSample for more information. | ||
--> | ||
<!-- The compressionLevel attribute specifies the amount of compression to perform. | ||
Valid values are 0 though 8 (integers only) with 0 producing the fastest encoding and least amount of compression and 8 | ||
producing the slowest encoding and greatest amount of compression. Values between 5 and 8 are popular. | ||
--> | ||
<flac bitsPerSample="24" compressionLevel="8"> | ||
<!-- The flacPath element specifies the location of flac.exe. | ||
Cross Time DSP invokes flac.exe and metaflac.exe to convert between .wav and .flac files. It is assumed metaflac.exe | ||
is in the same directory as flac.exe. flac.exe can be obtained from http://sourceforge.net/projects/flac/ by | ||
downloading and running the Windows installer. | ||
--> | ||
<flacPath>C:\Program Files (x86)\FLAC Frontend\tools\flac.exe</flacPath> | ||
</flac> | ||
<!-- The mp3 element specifies options for MP3 files. It is ignored when the input encoding is not MP3. --> | ||
<mp3> | ||
<!-- The lamePath element specifies the location of lame.exe. | ||
Cross Time DSP invokes lame.exe to convert between .mp3 and .wav files. The LAME project does not distribute binaries but | ||
does link a number of distributions from http://lame.sourceforge.net/links.php. LAME does not support extraction of tags | ||
so MP3 metadata is lost when converting from MP3 to .wav. | ||
--> | ||
<lamePath>C:\Program Files (x86)\Lame For Audacity\lame.exe</lamePath> | ||
</mp3> | ||
<!-- The wav element specifies options for WAVE files. It is used both when the output encoding is Wav and for the creation of | ||
intermediate .wav files which are transcoded to other formats such as FLAC. | ||
--> | ||
<!-- The bitsPerSample attribute specifies the bit depth of the output WAVE file. | ||
Supported values are 16 and 24 bit. When filters are applied it is suggested to default to 24 bit and treat the output .wav as | ||
a "master" for encoding to other formats such as AAC, MP3, or Ogg Vorbis. Cross Time DSP does this internally when encoding to | ||
FLAC so the wav bitsPerSample attribute should nominally be equal to or higher than the [flac@bitsPerSample] attribute. If | ||
subjective testing finds no difference between 16 and 24 bit or if storage space is limited then the output can be reduced to 16 | ||
bits per sample. However, flac.exe ignores the output bit depths which are smaller than the input bit depth so, if one wants 16 | ||
bit FLAC output, the wav bits per sample must also be set to 16. | ||
--> | ||
<wav bitsPerSample="24"/> | ||
</output> | ||
</crossTimeDsp> | ||
<!-- Cross Time DSP uses standard .NET tracing. It's rather unlikely you'll need to change any settings here. --> | ||
<system.diagnostics> | ||
<trace autoflush="true" indentsize="2"> | ||
<listeners> | ||
<add name="consoleListener" type="CrossTimeDsp.Common.ConsoleTraceListener, CrossTimeDsp"/> | ||
</listeners> | ||
</trace> | ||
</system.diagnostics> | ||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/></startup></configuration> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
using System; | ||
using System.Diagnostics; | ||
|
||
namespace CrossTimeDsp.Common | ||
{ | ||
internal class ConsoleTraceListener : System.Diagnostics.ConsoleTraceListener | ||
{ | ||
public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message) | ||
{ | ||
switch (eventType) | ||
{ | ||
// TraceListener.TraceEvent() includes the source, event type, and id as well as the message | ||
// this information has no value to users reading the traces on the console, so suppress it | ||
case TraceEventType.Information: | ||
Console.WriteLine(message.PadLeft(message.Length + this.IndentLevel * this.IndentSize)); | ||
break; | ||
// if needed, special case other event types | ||
default: | ||
base.TraceEvent(eventCache, source, eventType, id, message); | ||
break; | ||
} | ||
} | ||
|
||
// nearly identical to the previous overload, but it's improper to use method forwarding as Console.WriteLine(string) and | ||
// Console.WriteLine(string, params object[]) have different behaviors in how the string is formatted | ||
public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object[] args) | ||
{ | ||
switch (eventType) | ||
{ | ||
case TraceEventType.Information: | ||
Console.WriteLine(format.PadLeft(format.Length + this.IndentLevel * this.IndentSize), args); | ||
break; | ||
default: | ||
base.TraceEvent(eventCache, source, eventType, id, format, args); | ||
break; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.Text; | ||
|
||
namespace CrossTimeDsp.Common | ||
{ | ||
internal class ProcessExecutor | ||
{ | ||
private static readonly TimeSpan DefaultExecutionTimeout = TimeSpan.FromMinutes(5); | ||
private string executablePath; | ||
public TimeSpan ExecutionTimeout { get; set; } | ||
|
||
public ProcessExecutor(string executablePath) | ||
{ | ||
this.executablePath = executablePath; | ||
this.ExecutionTimeout = ProcessExecutor.DefaultExecutionTimeout; | ||
} | ||
|
||
private string EscapeArgument(string argument) | ||
{ | ||
return argument.Replace("\"", "\\\""); | ||
} | ||
|
||
public string Execute(List<string> arguments) | ||
{ | ||
Process process = new Process(); | ||
process.StartInfo = new ProcessStartInfo(this.executablePath); | ||
if (arguments != null && arguments.Count > 0) | ||
{ | ||
StringBuilder argumentBuilder = new StringBuilder(String.Format("\"{0}\"", this.EscapeArgument(arguments[0]))); | ||
for (int argument = 1; argument < arguments.Count; ++argument) | ||
{ | ||
argumentBuilder.AppendFormat(" \"{0}\"", this.EscapeArgument(arguments[argument])); | ||
} | ||
process.StartInfo.Arguments = argumentBuilder.ToString(); | ||
} | ||
process.StartInfo.CreateNoWindow = true; | ||
process.StartInfo.ErrorDialog = false; | ||
process.StartInfo.RedirectStandardOutput = true; | ||
process.StartInfo.UseShellExecute = false; | ||
if (process.Start() == false) | ||
{ | ||
throw new ApplicationException(String.Format("Failed to start '\"{0}\" {1}'", this.executablePath, process.StartInfo.Arguments)); | ||
} | ||
// if needed, capture standard error as well (requires async read to avoid deadlocks) | ||
string standardOutput = process.StandardOutput.ReadToEnd(); | ||
if (process.WaitForExit((int)this.ExecutionTimeout.TotalMilliseconds) == false) | ||
{ | ||
throw new ApplicationException(String.Format("Task '\"{0}\" {1}' failed to complete in {2}.", this.executablePath, process.StartInfo.Arguments, this.ExecutionTimeout)); | ||
} | ||
if (process.ExitCode != 0) | ||
{ | ||
throw new ApplicationException(String.Format("Task '\"{0}\" {1}' exited with code {2}.\nStandard output was '{3}'.", this.executablePath, process.StartInfo.Arguments, process.ExitCode, standardOutput)); | ||
} | ||
return standardOutput; | ||
} | ||
} | ||
} |
Oops, something went wrong.