Skip to content

Commit

Permalink
build: populate tree
Browse files Browse the repository at this point in the history
  • Loading branch information
twest820 committed Dec 17, 2016
0 parents commit f2ed2ca
Show file tree
Hide file tree
Showing 78 changed files with 4,299 additions and 0 deletions.
19 changes: 19 additions & 0 deletions .gitignore
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/
47 changes: 47 additions & 0 deletions CrossTimeDsp.sln
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
163 changes: 163 additions & 0 deletions CrossTimeDsp/App.config
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>
39 changes: 39 additions & 0 deletions CrossTimeDsp/Common/ConsoleTraceListener.cs
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;
}
}
}
}
59 changes: 59 additions & 0 deletions CrossTimeDsp/Common/ProcessExecutor.cs
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;
}
}
}
Loading

0 comments on commit f2ed2ca

Please sign in to comment.