NLayer MpegFile转换为SFML.净SoundStream
本文关键字:SoundStream SFML MpegFile 转换 NLayer | 更新日期: 2023-09-27 18:07:00
我目前正在研究SFML。Net扩展与mp3支持。因此,我写了一个Stream类,使用NLayer MpegFile来解码mp3。
public class Mp3StreamSFML : SoundStream
{
private MpegFile mp3file;
private int currentBufferSize;
private short[] currentBuffer;
public Mp3StreamSFML(String _filename)
{
mp3file = new MpegFile(_filename);
Initialize((uint)mp3file.Channels, (uint)mp3file.SampleRate);
currentBufferSize = 0;
currentBuffer = new short[currentBufferSize];
}
#region implemented abstract members of SoundStream
protected override bool OnGetData(out short[] samples)
{
if (currentBufferSize <= mp3file.Position)
{
byte[] buffer = new byte[512];
if (mp3file.ReadSamples(buffer, 0, buffer.Length) > 0)
{
Array.Resize(ref currentBuffer, currentBuffer.Length + (buffer.Length / 2));
Buffer.BlockCopy(buffer, 0, currentBuffer, currentBufferSize, buffer.Length);
currentBufferSize = currentBuffer.Length;
}
samples = currentBuffer;
return true;
}
else
{
samples = currentBuffer;
return false;
}
}
protected override void OnSeek(TimeSpan timeOffset)
{
mp3file.Position = (long)timeOffset.TotalSeconds;
}
#endregion
}
我是这样用的:
try
{
stream = new Mp3StreamSFML(this.objProgram.getObjCuesheet().getAudiofilePath(true));
stream.Play();
log.debug("samplerate = " + stream.SampleRate);
}
catch(Exception ex)
{
log.fatal(ex.ToString());
}
不幸的是,没有正确的声音播放,它只是"抖动",听起来真的很奇怪。我做错了什么?似乎是两个框架之间的问题。
谢谢你的帮助。斯文
是这样解决的:
using System;
using SFML.Audio;
using NLayer;
using System.Threading;
namespace AudioCuesheetEditor.AudioBackend.SFML
{
/// <summary>
/// Class for mp3 decoded audio files to use in SFML as Soundstream, since SFML doesn't support mp3 decoding (for legal reasons).
/// </summary>
public class Mp3StreamSFML : SoundStream
{
private static readonly Logfile log = Logfile.getLogfile(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private MpegFile mp3file;
private Mutex mutex;
/// <summary>
/// Initializes a new instance of the <see cref="AudioCuesheetEditor.AudioBackend.SFML.Mp3StreamSFML"/> class.
/// </summary>
/// <param name="_filename">Full path to the file</param>
public Mp3StreamSFML(String _filename)
{
log.debug("Constructor called with " + _filename);
this.mp3file = new MpegFile(_filename);
this.Initialize((uint)this.mp3file.Channels, (uint)this.mp3file.SampleRate);
this.mutex = new Mutex();
}
public TimeSpan Duration
{
get
{
log.debug("Duration = " + this.mp3file.Duration);
return this.mp3file.Duration;
}
}
#region implemented abstract members of SoundStream
protected override bool OnGetData(out short[] samples)
{
log.debug("OnGetData called");
this.mutex.WaitOne();
//Buffer data for about 1 second
float[] normalizedaudiodata = new float[48000];
int readSamples = this.mp3file.ReadSamples(normalizedaudiodata, 0, normalizedaudiodata.Length);
short[] pcmaudiodata;
if (readSamples > 0)
{
pcmaudiodata = new short[readSamples]; // converted data
for (int i = 0; i < readSamples; i++)
{
// clip the data
if (normalizedaudiodata[i] > 1.0f)
{
normalizedaudiodata[i] = 1.0f;
}
else
{
if (normalizedaudiodata[i] < -1.0f)
{
normalizedaudiodata[i] = -1.0f;
}
}
// convert to pcm data
pcmaudiodata[i] = (short)(normalizedaudiodata[i] * short.MaxValue);
}
samples = pcmaudiodata;
this.mutex.ReleaseMutex();
return true;
}
else
{
samples = null;
this.mutex.ReleaseMutex();
return false;
}
}
protected override void OnSeek(TimeSpan timeOffset)
{
log.debug("OnSeek called with " + timeOffset);
this.mutex.WaitOne();
if ((timeOffset <= this.mp3file.Duration) && (timeOffset >= TimeSpan.Zero))
{
this.mp3file.Time = timeOffset;
}
this.mutex.ReleaseMutex();
}
#endregion
}
}