98 lines
3.4 KiB
C#
98 lines
3.4 KiB
C#
using System.Text.Json.Serialization;
|
|
using Konata.Codec.Audio;
|
|
using Konata.Codec.Audio.Codecs;
|
|
using Lagrange.Core.Message;
|
|
using Lagrange.Core.Message.Entity;
|
|
using Lagrange.OneBot.Utility;
|
|
|
|
namespace Lagrange.OneBot.Message.Entity;
|
|
|
|
[Serializable]
|
|
public partial class RecordSegment(string url)
|
|
{
|
|
public RecordSegment() : this("") { }
|
|
|
|
[JsonPropertyName("file")][CQProperty] public string File { get; set; } = url;
|
|
|
|
[JsonPropertyName("url")] public string Url { get; set; } = url;
|
|
}
|
|
|
|
[SegmentSubscriber(typeof(RecordEntity), "record")]
|
|
public partial class RecordSegment : SegmentBase
|
|
{
|
|
public override void Build(MessageBuilder builder, SegmentBase segment)
|
|
{
|
|
if (segment is RecordSegment recordSegment and not { File: "" } && CommonResolver.Resolve(recordSegment.File) is { } record)
|
|
{
|
|
byte[] silk = ConvertFormat(record, out double time);
|
|
builder.Record(silk, (int)Math.Ceiling(time));
|
|
}
|
|
}
|
|
|
|
public override SegmentBase FromEntity(MessageChain chain, IMessageEntity entity)
|
|
{
|
|
if (entity is not RecordEntity recordEntity) throw new ArgumentException("Invalid entity type.");
|
|
|
|
return new RecordSegment(recordEntity.AudioUrl);
|
|
}
|
|
|
|
private static byte[] ConvertFormat(byte[] audio, out double audioTime)
|
|
{
|
|
var format = AudioHelper.DetectAudio(audio);
|
|
switch (format) // Process
|
|
{
|
|
// Silk v3 for tx use
|
|
case AudioHelper.AudioFormat.TenSilkV3:
|
|
{
|
|
audioTime = AudioHelper.GetTenSilkTime(audio);
|
|
return audio;
|
|
}
|
|
|
|
// Amr format
|
|
// We no need to convert it
|
|
case AudioHelper.AudioFormat.Amr:
|
|
{
|
|
audioTime = audio.Length / 1607.0;
|
|
return audio;
|
|
}
|
|
|
|
// Normal silk v3
|
|
// We need to append a header 0x02
|
|
// and remove 0xFFFF end for it
|
|
case AudioHelper.AudioFormat.SilkV3:
|
|
{
|
|
audio = [0x02, .. audio.AsSpan(0, audio.Length - 2)];
|
|
audioTime = AudioHelper.GetTenSilkTime(audio);
|
|
return audio;
|
|
}
|
|
|
|
// Need to convert
|
|
case AudioHelper.AudioFormat.Wav:
|
|
case AudioHelper.AudioFormat.Ogg:
|
|
case AudioHelper.AudioFormat.Mp3:
|
|
{
|
|
var input = new MemoryStream(audio);
|
|
var output = new MemoryStream();
|
|
|
|
var pipeline = new AudioPipeline() {
|
|
format switch {
|
|
AudioHelper.AudioFormat.Wav => new WavCodec.Decoder(input),
|
|
AudioHelper.AudioFormat.Ogg => new VorbisCodec.Decoder(input),
|
|
AudioHelper.AudioFormat.Mp3 => new Mp3Codec.Decoder(input),
|
|
_ => throw new Exception("Unknown Fromat")
|
|
},
|
|
new AudioResampler(AudioInfo.SilkV3()),
|
|
new SilkV3Codec.Encoder(),
|
|
output
|
|
};
|
|
if (!pipeline.Start().Result) throw new Exception("Encode failed");
|
|
|
|
audioTime = pipeline.GetAudioTime();
|
|
return output.ToArray();
|
|
}
|
|
|
|
// Cannot convert unknown type
|
|
default: throw new Exception("Unknown Fromat");
|
|
}
|
|
}
|
|
} |