Skip to content
Permalink
Browse files

Merge remote-tracking branch 'origin/master' into onecsproj_onexkpkg2

# Conflicts:
#	Xenko.xkpkg
#	sources/shared/SharedAssemblyInfo.cs
  • Loading branch information
xen2 committed Nov 21, 2018
2 parents 50412ba + a7db66d commit be8bb7ddd8fff36c3f2abbb4404f442848f0ea00
@@ -40,6 +40,9 @@ Thank you everybody for your generous contributions!
* Beliar
* Robert Iadanza
* SleepyMode
* Marko Viitanen
* David R Miller
* Sven-Bertil Blom

## Mini Backers

@@ -93,6 +93,11 @@ public override int GetHashCode()
}
}

public override string ToString()
{
return $"{DependencyType}: {Source} => {Target}";
}

/// <inheritdoc/>
public static bool operator ==(BuildAssetLink left, BuildAssetLink right)
{
@@ -235,6 +240,11 @@ private void AddDependencies(AssetItem assetItem, HashSet<BuildDependencyInfo> t
}
}

public override string ToString()
{
return $"{AssetItem.Location} ({References.Count} refs)";
}

private class RuntimeDependenciesCollector : AssetVisitorBase
{
private object visitedRuntimeObject;
@@ -229,7 +229,7 @@ public bool IsDirty

public override string ToString()
{
return $"[{Asset.GetType().Name}] {location} => {Id}";
return $"[{Asset.GetType().Name}] {location}";
}

/// <summary>
@@ -6,6 +6,10 @@
using Xenko.Core.Assets.Analysis;
using Xenko.Core.BuildEngine;
using Xenko.Core.Annotations;
using System.Threading.Tasks;
using Xenko.Core.Diagnostics;
using Xenko.Core.Extensions;
using System.Linq;

namespace Xenko.Core.Assets.Compiler
{
@@ -85,19 +89,21 @@ public AssetCompilerResult Prepare(AssetCompilerContext context, AssetItem asset

if ((dependencyType & BuildDependencyType.Runtime) == BuildDependencyType.Runtime && compilerResult.HasErrors) //allow Runtime dependencies to fail
{
//totally skip this asset but do not propagate errors!
return;
assetBuildSteps = new ErrorBuildStep(assetItem, compilerResult.Messages);
}
else
{

assetBuildSteps = compilerResult.BuildSteps;
compiledItems.Add(assetNode.AssetItem.Id, assetBuildSteps);
assetBuildSteps = compilerResult.BuildSteps;
compiledItems.Add(assetNode.AssetItem.Id, assetBuildSteps);

// Copy the log to the final result (note: this does not copy or forward the build steps)
compilerResult.CopyTo(finalResult);
if (compilerResult.HasErrors)
{
finalResult.Error($"Failed to prepare asset {assetItem.Location}");
return;
// Copy the log to the final result (note: this does not copy or forward the build steps)
compilerResult.CopyTo(finalResult);
if (compilerResult.HasErrors)
{
finalResult.Error($"Failed to prepare asset {assetItem.Location}");
return;
}
}

// Add the resulting build steps to the final
@@ -126,5 +132,23 @@ public AssetCompilerResult Prepare(AssetCompilerContext context, AssetItem asset
if (parentBuildStep != null && assetBuildSteps != null && (dependencyType & BuildDependencyType.CompileContent) == BuildDependencyType.CompileContent) //only if content is required Content.Load
BuildStep.LinkBuildSteps(assetBuildSteps, parentBuildStep);
}

private class ErrorBuildStep : AssetBuildStep
{
private readonly List<ILogMessage> messages;

public ErrorBuildStep(AssetItem assetItem, IEnumerable<ILogMessage> messages)
: base(assetItem)
{
this.messages = messages.ToList();
}

public override Task<ResultStatus> Execute(IExecuteContext executeContext, BuilderContext builderContext)
{
foreach (var message in messages)
executeContext.Logger.Log(message);
return Task.FromResult(ResultStatus.Failed);
}
}
}
}
@@ -34,6 +34,7 @@ protected class DecodeSoundFileCommand : AssetCommand<SoundAsset>
public DecodeSoundFileCommand(string url, SoundAsset parameters, IAssetFinder assetFinder)
: base(url, parameters, assetFinder)
{
Version = 1;
}

/// <inheritdoc />
@@ -98,11 +99,12 @@ protected override async Task<ResultStatus> DoCommandOverride(ICommandContext co
writer.Write((short)len);
outputStream.Write(outputBuffer, 0, len);

count = 0;
Array.Clear(buffer, 0, frameSize);

newSound.Samples += count / channels;
newSound.NumberOfPackets++;
newSound.MaxPacketLength = Math.Max(newSound.MaxPacketLength, len);

count = 0;
Array.Clear(buffer, 0, frameSize);
}

buffer[count] = reader.ReadSingle();
@@ -115,6 +117,7 @@ protected override async Task<ResultStatus> DoCommandOverride(ICommandContext co
writer.Write((short)len);
outputStream.Write(outputBuffer, 0, len);

newSound.Samples += count / channels;
newSound.NumberOfPackets++;
newSound.MaxPacketLength = Math.Max(newSound.MaxPacketLength, len);
}
@@ -39,6 +39,7 @@ internal sealed class CompressedSoundSource : DynamicSoundSource

private readonly int channels;
private readonly int sampleRate;
private readonly int samples;

private readonly int maxCompressedSize;
private byte[] compressedBuffer;
@@ -50,7 +51,7 @@ internal sealed class CompressedSoundSource : DynamicSoundSource
private byte[] byteBuffer = null;
private int byteBufferCurrentPosition = 0;

public CompressedSoundSource(SoundInstance instance, byte[] byteBuffer, int numberOfPackets, int sampleRate, int channels, int maxCompressedSize)
public CompressedSoundSource(SoundInstance instance, byte[] byteBuffer, int numberOfPackets, int numberOfSamples, int sampleRate, int channels, int maxCompressedSize)
: base(instance, NumberOfBuffers, SamplesPerBuffer * MaxChannels * sizeof(short))
{
looped = instance.IsLooping;
@@ -60,6 +61,7 @@ public CompressedSoundSource(SoundInstance instance, byte[] byteBuffer, int numb
this.byteBuffer = byteBuffer;
this.sampleRate = sampleRate;
this.numberOfPackets = numberOfPackets;
this.samples = numberOfSamples;
playRange = new PlayRange(TimeSpan.Zero, TimeSpan.Zero);

NewSources.Add(this);
@@ -78,7 +80,7 @@ public CompressedSoundSource(SoundInstance instance, byte[] byteBuffer, int numb
/// <param name="sampleRate">The sample rate of the compressed data</param>
/// <param name="channels">The number of channels of the compressed data</param>
/// <param name="maxCompressedSize">The maximum size of a compressed packet</param>
public CompressedSoundSource(SoundInstance instance, IVirtualFileProvider fileProvider, string soundStreamUrl, int numberOfPackets, int sampleRate, int channels, int maxCompressedSize)
public CompressedSoundSource(SoundInstance instance, IVirtualFileProvider fileProvider, string soundStreamUrl, int numberOfPackets, int numberOfSamples, int sampleRate, int channels, int maxCompressedSize)
: base(instance, NumberOfBuffers, SamplesPerBuffer * MaxChannels * sizeof(short))
{
looped = instance.IsLooping;
@@ -88,6 +90,7 @@ public CompressedSoundSource(SoundInstance instance, IVirtualFileProvider filePr
this.soundStreamUrl = soundStreamUrl;
this.sampleRate = sampleRate;
this.numberOfPackets = numberOfPackets;
this.samples = numberOfSamples;
playRange = new PlayRange(TimeSpan.Zero, TimeSpan.Zero);

NewSources.Add(this);
@@ -153,30 +156,36 @@ protected override void PrepareInternal()
range = playRange;
}

if (range.Start != TimeSpan.Zero || range.Length != TimeSpan.Zero)
{
var frameSize = SamplesPerFrame * channels;
//ok we need to handle this case properly, this means that the user wants to use a different then full audio stream range...
var sampleStart = sampleRate * (double)channels * range.Start.TotalSeconds;
startPktSampleIndex = (int)Math.Floor(sampleStart) % (frameSize);
// Reset decoder state
decoder.ResetDecoder();

// Ignore invalid data at beginning (due to encoder delay) & end of stream (due to packet size)
var samplesToSkip = decoder.GetDecoderSampleDelay();

var sampleStop = sampleRate * (double)channels * range.End.TotalSeconds;
endPktSampleIndex = frameSize - (int)Math.Floor(sampleStart) % frameSize;
var frameSize = SamplesPerFrame * channels;
//ok we need to handle this case properly, this means that the user wants to use a different then full audio stream range...
var sampleStart = (channels * samplesToSkip) + (int)Math.Floor(sampleRate * (double)channels * range.Start.TotalSeconds);
startPktSampleIndex = sampleStart % (frameSize);

var skipCounter = startingPacketIndex = (int)Math.Floor(sampleStart / frameSize);
endPacketIndex = (int)Math.Floor(sampleStop / frameSize);
var sampleStop = (channels * samplesToSkip)
+ (range.Length != TimeSpan.Zero
? (int)Math.Floor(sampleRate * (double)channels * range.End.TotalSeconds)
: (channels * samples));
endPktSampleIndex = frameSize - sampleStop % frameSize;

// skip to the starting packet
if (startingPacketIndex < numberOfPackets && endPacketIndex < numberOfPackets && startingPacketIndex < endPacketIndex)
var skipCounter = startingPacketIndex = sampleStart / frameSize;
endPacketIndex = sampleStop / frameSize;

// skip to the starting packet
if (startingPacketIndex < numberOfPackets && endPacketIndex < numberOfPackets && startingPacketIndex < endPacketIndex)
{
//valid offsets.. process it
while (skipCounter-- > 0)
{
//valid offsets.. process it
while (skipCounter-- > 0)
{
//skip data to reach starting packet
var len = reader.ReadInt16();
compressedSoundStream.Position = compressedSoundStream.Position + len;
currentPacketIndex++;
}
//skip data to reach starting packet
var len = reader.ReadInt16();
compressedSoundStream.Position = compressedSoundStream.Position + len;
currentPacketIndex++;
}
}
}
@@ -46,6 +46,16 @@ extern "C" {
delete celt;
}

DLL_EXPORT_API void xnCeltResetDecoder(XenkoCelt* celt)
{
opus_custom_decoder_ctl(celt->GetDecoder(), OPUS_RESET_STATE);
}

DLL_EXPORT_API int xnCeltGetDecoderSampleDelay(XenkoCelt* celt, int32_t* delay)
{
return opus_custom_decoder_ctl(celt->GetDecoder(), OPUS_GET_LOOKAHEAD(delay));
}

DLL_EXPORT_API int xnCeltEncodeFloat(XenkoCelt* celt, float* inputSamples, int numberOfInputSamples, uint8_t* outputBuffer, int maxOutputSize)
{
return opus_custom_encode_float(celt->GetEncoder(), inputSamples, numberOfInputSamples, outputBuffer, maxOutputSize);
@@ -88,6 +88,26 @@ public unsafe int Decode(byte[] inputBuffer, int inputBufferSize, short* outputS
}
}

/// <summary>
/// Reset decoder state.
/// </summary>
public void ResetDecoder()
{
xnCeltResetDecoder(celtPtr);
}

/// <summary>
/// Gets the delay between encoder and decoder (in number of samples). This should be skipped at the beginning of a decoded stream.
/// </summary>
/// <returns></returns>
public int GetDecoderSampleDelay()
{
var delay = 0;
if (xnCeltGetDecoderSampleDelay(celtPtr, ref delay) != 0)
delay = 0;
return delay;
}

/// <summary>
/// Encode PCM audio into celt compressed format
/// </summary>
@@ -142,6 +162,14 @@ public unsafe int Encode(float[] audioSamples, byte[] outputBuffer)
[DllImport(NativeInvoke.Library, CallingConvention = CallingConvention.Cdecl)]
private static extern void xnCeltDestroy(IntPtr celt);

[SuppressUnmanagedCodeSecurity]
[DllImport(NativeInvoke.Library, CallingConvention = CallingConvention.Cdecl)]
private static extern int xnCeltResetDecoder(IntPtr celt);

[SuppressUnmanagedCodeSecurity]
[DllImport(NativeInvoke.Library, CallingConvention = CallingConvention.Cdecl)]
private static extern int xnCeltGetDecoderSampleDelay(IntPtr celt, ref int delay);

[SuppressUnmanagedCodeSecurity]
[DllImport(NativeInvoke.Library, CallingConvention = CallingConvention.Cdecl)]
private static extern unsafe int xnCeltEncodeFloat(IntPtr celt, float* inputSamples, int numberOfInputSamples, byte* outputBuffer, int maxOutputSize);
@@ -31,6 +31,8 @@ public sealed class Sound : SoundBase

internal IVirtualFileProvider FileProvider;

internal int Samples { get; set; }

/// <summary>
/// Create a new sound effect instance of the sound effect.
/// The audio data are shared between the instances so that useless memory copies is avoided.
@@ -96,7 +98,9 @@ internal void LoadSoundInMemory()
offset += samplesDecoded * Channels * sizeof(short);
}

AudioLayer.BufferFill(PreloadedBuffer, memory.Pointer, memory.Length * sizeof(short), SampleRate, Channels == 1);
// Ignore invalid data at beginning (due to encoder delay) & end of stream (due to packet size)
var samplesToSkip = decoder.GetDecoderSampleDelay();
AudioLayer.BufferFill(PreloadedBuffer, memory.Pointer + samplesToSkip * Channels * sizeof(short), Samples * Channels * sizeof(short), SampleRate, Channels == 1);
memory.Dispose();
}
}
@@ -81,7 +81,7 @@ internal SoundInstance(Sound staticSound, AudioListener listener, bool forceLoad

if (streamed)
{
soundSource = new CompressedSoundSource(this, staticSound.FileProvider, staticSound.CompressedDataUrl, staticSound.NumberOfPackets, staticSound.SampleRate, staticSound.Channels, staticSound.MaxPacketLength);
soundSource = new CompressedSoundSource(this, staticSound.FileProvider, staticSound.CompressedDataUrl, staticSound.NumberOfPackets, staticSound.Samples, staticSound.SampleRate, staticSound.Channels, staticSound.MaxPacketLength);
}
else
{
@@ -27,6 +27,7 @@ public override void Serialize(ref Sound obj, ArchiveMode mode, SerializationStr
obj.Spatialized = stream.ReadBoolean();
obj.NumberOfPackets = stream.ReadInt16();
obj.MaxPacketLength = stream.ReadInt16();
obj.Samples = stream.ReadInt32();

if (!obj.StreamFromDisk && audioEngine != null && audioEngine.State != AudioEngineState.Invalidated && audioEngine.State != AudioEngineState.Disposed) //immediatelly preload all the data and decode
{
@@ -47,6 +48,7 @@ public override void Serialize(ref Sound obj, ArchiveMode mode, SerializationStr
stream.Write(obj.Spatialized);
stream.Write((short)obj.NumberOfPackets);
stream.Write((short)obj.MaxPacketLength);
stream.Write(obj.Samples);
}
}
}
@@ -38,10 +38,13 @@ public static class Vertex
/// <param name="device">The <see cref="GraphicsDevice"/>.</param>
/// <param name="size">The size in bytes.</param>
/// <param name="usage">The usage.</param>
/// <returns>A Vertex buffer</returns>
public static Buffer New(GraphicsDevice device, int size, GraphicsResourceUsage usage = GraphicsResourceUsage.Default)
/// <param name="bindFlags">The bind flags, can be combined with <see cref="BufferFlags.StreamOutput"/> to use the buffer as a stream output target.</param>
/// <returns>
/// A Vertex buffer
/// </returns>
public static Buffer New(GraphicsDevice device, int size, GraphicsResourceUsage usage = GraphicsResourceUsage.Default, BufferFlags bindFlags = BufferFlags.VertexBuffer)
{
return Buffer.New(device, size, BufferFlags.VertexBuffer, usage);
return Buffer.New(device, size, bindFlags, usage);
}

/// <summary>
@@ -71,5 +71,10 @@ public enum BufferFlags
/// Creates an indirect arguments buffer.
/// </summary>
ArgumentBuffer = 1024,

/// <summary>
/// Creates a buffer for the geometry shader stream-output stage.
/// </summary>
StreamOutput = 2048,
}
}
@@ -240,6 +240,9 @@ private static SharpDX.Direct3D11.BufferDescription ConvertToNativeDescription(B
if ((bufferFlags & BufferFlags.ArgumentBuffer) == BufferFlags.ArgumentBuffer)
desc.OptionFlags |= ResourceOptionFlags.DrawIndirectArguments;

if ((bufferFlags & BufferFlags.StreamOutput) != 0)
desc.BindFlags |= BindFlags.StreamOutput;

return desc;
}

0 comments on commit be8bb7d

Please sign in to comment.
You can’t perform that action at this time.