Skip to content

Instantly share code, notes, and snippets.

@rhaly
Last active March 25, 2019 08:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rhaly/7fb802430656975d5fcb3a73bb449a19 to your computer and use it in GitHub Desktop.
Save rhaly/7fb802430656975d5fcb3a73bb449a19 to your computer and use it in GitHub Desktop.
bass.pcm problem
public class AudioPlayer
{
public void Play()
{
if (State.HasFlag(PlayerState.NotInitialized))
{
InitializeAudioFile();
if (State.HasFlag(PlayerState.NotInitialized) || State.HasFlag(PlayerState.Faulted))
{
return;
}
}
State = PlayerState.Playing;
_audioLibrary.SetTempo(StreamFx, PlaybackSpeed);
_audioLibrary.SetVolume(StreamFx, _audioVolume);
_audioLibrary.HandleOnStreamEnded(StreamFx, OnStreamEnded);
_audioLibrary.SetPosition(StreamFx, audioList.CurrentAudioFile.CurrentPosition);
_audioLibrary.Play(StreamFx);
}
private void InitializeAudioFile(bool force = false)
{
if (State.HasFlag(PlayerState.NotInitialized) || force)
{
InitializeDevice();
try
{
var path = audioList.CurrentAudioFile.FileUri.LocalPath;
Stream = _audioLibrary.CreateStream(audioList.DecoderService, path);
}
catch (EndOfStreamException e)
{
State = PlayerState.Faulted;
OnStreamEnded();
return;
}
catch (Exception e)
{
State = PlayerState.Faulted;
return;
}
if (Stream == 0)
{
Stop();
}
StreamFx = _audioLibrary.ConvertStreamToTempoChangeableStream(Stream);
State |= PlayerState.Initialized;
}
}
private void InitializeDevice()
{
lock (_initSync)
{
if (_deviceInitialized)
{
return;
}
if (_audioLibrary.Initialize() == false)
{
LogService.Debug(Tag, " Audio device not initialized");
State = PlayerState.NotInitialized;
}
_deviceInitialized = true;
State = PlayerState.Initialized;
}
}
}
public class BassAudioLibrary : IAudioLibrary
{
private static Stream _fs;
public bool Initialize()
{
try
{
Bass.BASS_SetConfig((BASSConfig) 50, 1);
var bassInit = Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero);
if (bassInit == false)
{
var bassErrorGetCode = Bass.BASS_ErrorGetCode();
Console.WriteLine($"Audio not initialized with error {bassErrorGetCode}");
}
else
{
TryToRemoveBassTmpFile();
}
}
catch (Exception e)
{
this.LogReport(e, "Unable to init bass lib");
Console.WriteLine(e);
}
return false;
}
private void TryToRemoveBassTmpFile()
{
#if __ANDROID__
try
{
var externalStorageDirectory = global::Android.OS.Environment.ExternalStorageDirectory;
var absolutePath = externalStorageDirectory.AbsolutePath;
Console.WriteLine(absolutePath);
var tmpFile = Path.Combine(absolutePath, "bass.pcm");
if (File.Exists(tmpFile))
{
File.Delete(tmpFile);
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
#endif
}
public int ConvertStreamToTempoChangeableStream(int stream)
{
return BassFx.BASS_FX_TempoCreate(stream, BASSFlag.BASS_FX_FREESOURCE);
}
public bool SetTempo(int stream, float tempo)
{
return Bass.BASS_ChannelSetAttribute(stream, BASSAttribute.BASS_ATTRIB_TEMPO, (tempo * 100 - 100));
}
public bool Play(int stream, bool restart = false)
{
Bass.BASS_ChannelPlay(stream, restart);
BASSError error = Bass.BASS_ErrorGetCode();
return error == BASSError.BASS_OK;
}
public int ConvertStreamToTempoChangeableStream(int stream)
{
return BassFx.BASS_FX_TempoCreate(stream, BASSFlag.BASS_FX_FREESOURCE);
}
public int CreateStream(IAudioDecoderService decoder, string filePath)
{
var myStreamCreateUser = new BASS_FILEPROCS(
new FILECLOSEPROC(OnCloseStream),
new FILELENPROC(OnGetStreamLength),
new FILEREADPROC(OnReadStream),
new FILESEEKPROC(OnSeekStream));
_fs = decoder.Open(filePath);
return Bass.BASS_StreamCreateFileUser(BASSStreamSystem.STREAMFILE_NOBUFFER, BASSFlag.BASS_STREAM_DECODE, myStreamCreateUser, IntPtr.Zero);
}
private static bool OnSeekStream(long offset, IntPtr user)
{
if (_fs == null)
return false;
try
{
var pos = _fs.Seek(offset, SeekOrigin.Begin);
return true;
}
catch
{
return false;
}
}
private static int OnReadStream(IntPtr buffer, int length, IntPtr user)
{
if (_fs == null)
return 0;
try
{
// at first we need to create a byte[] with the size of the requested length
var data = new byte[length];
// read the file into data
var bytesread = _fs.Read(data, 0, length);
// and now we need to copy the data to the buffer
// we write as many bytes as we read via the file operation
Marshal.Copy(data, 0, buffer, bytesread);
return bytesread;
}
catch (Exception e)
{
Debug.WriteLine("Error Reading stream :" + e);
return 0;
}
}
private static long OnGetStreamLength(IntPtr user)
{
if (_fs == null)
return 0L;
return _fs.Length;
}
private static void OnCloseStream(IntPtr user)
{
ClearStream();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment