Author Topic: trying to convert MIDI to OGG and failing  (Read 1910 times)

Brannon

  • Posts: 16
trying to convert MIDI to OGG and failing
« on: 20 Mar '12 - 04:27 »
I've got some code here for converting a MIDI to an OGG file. However, the EncodeFile call returns false immediately. The error code is BASS_OK. What am I doing wrong? Thanks for any help.

Code: [Select]
private void convertBtn_Click(object sender, RoutedEventArgs e)
{
var bg = new BackgroundWorker();
bg.WorkerReportsProgress = true;

var inputFilename = inputTxt.Text;
var outputFilename = outputTxt.Text;
progressBar.Maximum = 100;
bg.ProgressChanged += (s, args) => progressBar.Value = args.ProgressPercentage;

bg.DoWork += delegate{
var TargetPath = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), Utils.Is64Bit ? "x64" : "x32");
Bass.LoadMe(TargetPath);
Bass.BASS_PluginLoad(Path.Combine(TargetPath, "bassmidi.dll"));

var sfH = BassMidi.BASS_MIDI_FontInit("SoundFonts/ChoriumRevA.SF2");

if(!Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero))
throw new Exception("Not able to init device. Code: " + Bass.BASS_ErrorGetCode());
int inputHandle = BassMidi.BASS_MIDI_StreamCreateFile(inputFilename, 0, 0, BASSFlag.BASS_MUSIC_DECODE | BASSFlag.BASS_MUSIC_FLOAT, 0);
if(inputHandle == 0)
throw new Exception("Unable to load MIDI file " + inputFilename + ". Code: " + Bass.BASS_ErrorGetCode());

var font = new BASS_MIDI_FONT(sfH, -1, 0);
if(!BassMidi.BASS_MIDI_StreamSetFonts(inputHandle, new[] { font }, 1))
throw new Exception("Unable to set the sound font for " + inputFilename + ". Code: " + Bass.BASS_ErrorGetCode());

var enc = new EncoderOGG(inputHandle);
enc.OutputFile = outputFilename;
if(!BaseEncoder.EncodeFile(enc, (bt, bd) => bg.ReportProgress((int)(bd*100/bt)), true, false))
throw new Exception("Unable to encode. Code: " + Bass.BASS_ErrorGetCode());

enc.Dispose();
Bass.BASS_StreamFree(inputHandle);
Bass.BASS_Free();
Bass.FreeMe();
};

bg.RunWorkerAsync();
}

aybe

  • Posts: 145
Re: trying to convert MIDI to OGG and failing
« Reply #1 on: 21 Mar '12 - 07:05 »
Do you have the DLLs in %System32% ?

Are you under 64-bit Windows ?
If so, you might want to check VS2010 menu Debug->Exceptions, make sure CLR exceptions are Thrown.
This is the default behavior in 64-bit, which can drive you crazy.
With this you'll be able to find out whether the error is in managed code (BASS.NET) or in its unmanaged part ...

Brannon

  • Posts: 16
Re: trying to convert MIDI to OGG and failing
« Reply #2 on: 21 Mar '12 - 13:38 »
My break-on-exceptions ability is enabled. I'm not seeing any exceptions other than the one thrown in my own code.

Exactly what DLLs in %SYSTEM% are you referring to? Are there some extra native DLLs necessary for converting to OGG? Thanks for your time.

aybe

  • Posts: 145
Re: trying to convert MIDI to OGG and failing
« Reply #3 on: 21 Mar '12 - 14:31 »
I mean the bass*.dll files  ;D

I just went through your code again,
BaseEncoder..::.ENCODEFILEPROC needs to be 'pinned' to a global field.
And yours doesn't seems to be of this type at all...

Have a look at this topic :

BASS.NET API for the Un4seen BASS Audio Library  
Interoperating with Unmanaged Code

(Page 2 of CHM)

Ian @ un4seen

  • Administrator
  • Posts: 20437
Re: trying to convert MIDI to OGG and failing
« Reply #4 on: 21 Mar '12 - 17:23 »
I'm not a .Net user myself, so I'm afraid I can't advise on the problem you're having with the BaseEncoder.EncodeFile call, but just to point out... I wouldn't recommend putting the DLLs in the SYSTEM32 directory as that can result in version conflicts if 2 or more apps do the same thing. It is better to place the DLLs in the executable's directory.

One thing that you could try, to narrow down what the problem is, is to call the encoder's Start method (instead of BaseEncoder.EncodeFile) and see whether that succeeds and what the error code is if it fails.

aybe

  • Posts: 145
Re: trying to convert MIDI to OGG and failing
« Reply #5 on: 21 Mar '12 - 18:11 »
Yes sorry, you're right,
I do this so I don't have to copy DLLs every time I make a new project but that's definitely not a good a practice.

Otherwise,  I think what I said on previous post should fix your problem,
a global field + a real ENCODERPROC, not BackgroundWorker's ReportProgress()

;D

Brannon

  • Posts: 16
Re: trying to convert MIDI to OGG and failing
« Reply #6 on: 22 Mar '12 - 03:51 »
aybe, I take it you're not familiar with first-class methods in C# (available since .NET 2.0)? The compiler automatically wraps my lambda in an ENCODERPROC. And it shouldn't need to be pinned because it's not going out of scope -- especially not with EncodeFile returning an immediate negative. EncodeFile is synchronous, true?

I'm not sure exactly what native DLLs I need to encode to OGG. I have right now bass.dll, bassenc.dll, and basemidi.dll. Am I missing something? Although I still get the same problem, I fixed up my test code to include this (and their disposals):

Code: [Select]
int p1 = Bass.BASS_PluginLoad(Path.Combine(TargetPath, "bassmidi.dll"));
int p2 = Bass.BASS_PluginLoad(Path.Combine(TargetPath, "bassenc.dll"));

Brannon

  • Posts: 16
Re: trying to convert MIDI to OGG and failing
« Reply #7 on: 22 Mar '12 - 05:04 »
I realized (after looking through the properties on enc) that I needed the oggenc2.exe file. I've now got that included. However, I still get an immediate negative. I added some asserts to make sure that EncoderExists was true.

I also realized, aybe, that you were talking about ENCODEPROC rather than ENCODEFILEPROC. The former is on the EncoderOGG.Start method. According to the documentation I shouldn't need that because I really do want to write to an output file. I suppose I could try it, but it's not clear to me how to determine when the encoding is complete if I use the Start method. Do I just poll the IsActive flag? That seems pretty lame in our world of event-driven programming.

radio42

  • Posts: 4576
Re: trying to convert MIDI to OGG and failing
« Reply #8 on: 22 Mar '12 - 10:41 »
The problem is another one:
You must specify a valid 'encoder.InputFile' before calling 'EncodeFile'.
The 'EncodeFile' method (as stated in the docs) actually uses the given 'encoder.InputFile' property and creates a stream internally itself.

That's also the reason, why you 'BaseEncoder.EncodeFile' call immediately returns 'false' (as no input filename was specified).
So in your case (where you need to encode an already prepared stream handle) you can NOT use the 'BaseEncoder.EncodeFile' method.
Instead you need to decode the data yourself, e.g. like this:
Code: [Select]
// stuff you already had in place in your code
...
// create an encoder
var enc = new EncoderOGG(inputHandle);
enc.InputFile = null; // use STDIN
enc.OutputFile = outputFilename;
// start the encoder
enc.Start(null, IntPtr.Zero, false);
// let the utils helper method decode all your data
// otherwise you can call BASS_ChannelGetData yourself
Utils.DecodeAllData(inputHandle, true);
enc.Dispose();
...

Brannon

  • Posts: 16
Re: trying to convert MIDI to OGG and failing
« Reply #9 on: 23 Mar '12 - 03:39 »
Thanks. It's working. Now on to changing the instruments in the file...