|
nr1
Posts: 78
|
 |
« Reply #920 on: 19 Jun '11 - 12:37 » |
Quote
|
No example available?
I would also need to create the WaveForm based on a bass stream on that it applied some filters before (low pass / high pass / etc.). Is this somehow possible?
|
|
|
|
|
Logged
|
|
|
|
|
radio42
Posts: 4012
|
 |
« Reply #921 on: 20 Jun '11 - 08:31 » |
Quote
|
There are several samples provided with Bass.Net. As written in the docs they are installed to your Application User Data directory. Once Bass.Net is installed, simply open the windows start menu, select 'Programs' and located the installed program menu 'BASS.NET API for .Net'. In this start menu you'll find a link to all provided samples. Regarding the WaveForm - take a look to the sample called 'Simple'.
|
|
|
|
|
Logged
|
|
|
|
|
nr1
Posts: 78
|
 |
« Reply #922 on: 20 Jun '11 - 21:22 » |
Quote
|
Yes i know the "simple" example, i just wanted to know if there is a demo app that shows all possibilities of the WaveForm class as the help shows a lot more features that aren't used in Simple demo. Furthermore because of my I would also need to create the WaveForm based on a bass stream on that it applied some filters before (low pass / high pass / etc.). Is this somehow possible? question: I can just find WaveForm constructors that need a filename. But i want to create the WaveForm based on a bass stream (that i put some dsp/fx effects on before). Is this somehow possible?
|
|
|
|
|
Logged
|
|
|
|
|
radio42
Posts: 4012
|
 |
« Reply #923 on: 21 Jun '11 - 09:03 » |
Quote
|
No, there is no sample which shows ALL features of the WaveForm class. But the docs contain a few more example codes.
There is no need to specify a FileName (see the default constructor). However, the WaveForm class needs a decoding channel (see the overloads of the 'RenderStart' method) - as such you can prepare such a decoding channel and pass it to the 'RenderStart' method. But note, that it will in any case render ALL the sample data of that decoding channel - meaning BASS_ChannelGetData is called internally in a loop until all data has been rendered! Only when using a 'RenderStart' overload which doesn't have a 'decodingStream' parameter the 'FileName' property is used to create a decoding stream on the fly.
|
|
|
|
|
Logged
|
|
|
|
|
nr1
Posts: 78
|
 |
« Reply #924 on: 21 Jun '11 - 21:17 » |
Quote
|
ok thx a lot it's working now: (little excerpt for all with similar question:) wave = new WaveForm(null, new WAVEFORMPROC(MyWaveFormCallback), wavePictureBox);
wave.RenderStart(_WaveChannel, false);
private void MyWaveFormCallback(int framesDone, int framesTotal, TimeSpan elapsedTime, bool finished) { waveCalculationProgress = Convert.ToByte((framesDone / Convert.ToSingle(framesTotal))*100);
if (finished) drawWave(); }
private void drawWave() { wavePictureBox.BackgroundImage = wave.CreateBitmap(wavePictureBox.Width, wavePictureBox.Height, -1, -1, true); }
One more question: In the simple example when zooming a waveform a moving marker that shows the playing position is shown. I would need the other way round: The marker (playing position) is always in the middle, but the background (wave) is moving / scrolling. How to do this best?
|
|
|
|
|
Logged
|
|
|
|
|
|
|
nr1
Posts: 78
|
 |
« Reply #926 on: 23 Jun '11 - 12:17 » |
Quote
|
Ok thx for your answer. To contribute i created a WaveFormDemo application that shows the most important features of the WaveForm. Whats missing at the moment in this demo is the visualisation of the playing position (showing playing position line, scrolling waveform, ..). Everyone feel free to add / correct features but make sure you also provide your changes here on the board. 
|
|
|
|
Logged
|
|
|
|
|
nr1
Posts: 78
|
 |
« Reply #927 on: 24 Jun '11 - 08:04 » |
Quote
|
@radio42: one more question: i'm trying to save a rendered waveform as binary file by executing wave.WaveFormSaveToFile(@"C:\Dokumente und Einstellungen\me\Desktop\BASS\WaveFormDemo\waveSavedByBass.txt",true);
The "waveSavedByBass.txt" file is created, but the filesize is always 4kb and the file's content is always " ". It's also not working if i try to to this byte[] waveForm = wave.WaveFormSaveToMemory(true);
as the byte array always is null after doing this. If i use the "standard" saving (binary = false) both methods are working. Any suggestions?
|
|
|
|
|
Logged
|
|
|
|
|
radio42
Posts: 4012
|
 |
« Reply #928 on: 24 Jun '11 - 08:30 » |
Quote
|
That's strange. I did a quick test here and it works fine without any issues. Is the WaveForm fully rendered when you try to save it? Ie. is the "wave.IsRendered" true? And what does "wave.WaveFormSaveToFile" return (true or false)?
|
|
|
|
|
Logged
|
|
|
|
|
nr1
Posts: 78
|
 |
« Reply #929 on: 24 Jun '11 - 08:51 » |
Quote
|
Ie. is the "wave.IsRendered" true? And what does "wave.WaveFormSaveToFile" return (true or false)?
hello, isRendered = true wave.WaveFormSaveToFile = false The file is anyway created although "wave.WaveFormSaveToFile" returns false.
|
|
|
|
|
Logged
|
|
|
|
|
radio42
Posts: 4012
|
 |
« Reply #930 on: 24 Jun '11 - 13:24 » |
Quote
|
Ahh, now I see what's going wrong in your provided sample. The "wave.FileName" property must actually be set before the "wave.WaveFormSaveToFile" method is being called. Here is the updated section, which will actually work. private void loadFile(String filename) { Bass.BASS_StreamFree(playChannel);
playChannel = Bass.BASS_StreamCreateFile(filename, 0L, 0L, BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_PRESCAN);
Task task = Task.Factory.StartNew(() => { if (System.IO.File.Exists(filename + ".wf")) { if (wave.WaveFormLoadFromFile(filename + ".wf", true)) { zoomEnd = wave.FramesToRender; drawWave(); } } else { int waveChannel = Bass.BASS_StreamCreateFile(filename, 0L, 0L, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_PRESCAN); wave.FileName = filename; if (wave.RenderStart(waveChannel, false)) { // save the waveform wave.WaveFormSaveToFile(filename + ".wf", true); } Bass.BASS_StreamFree(waveChannel); } }); }
However, in the next version I'll also allow the 'Filename' property to be null while saving the WavewForm!
|
|
|
|
|
Logged
|
|
|
|
|
nr1
Posts: 78
|
 |
« Reply #931 on: 24 Jun '11 - 17:59 » |
Quote
|
thx a lot, now it's working 
|
|
|
|
|
Logged
|
|
|
|
|
ken
Posts: 630
|
 |
« Reply #932 on: 26 Jun '11 - 13:20 » |
Quote
|
Hi Bernd, Sometimes I get this error on: Bass.BASS_StreamFree(_channel1); CallbackOnCollectedDelegate was detected Message: A callback was made on a garbage collected delegate of type 'Bass.Net!Un4seen.Bass.SYNCPROC::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.
Add stream to mixer like this: _channel1 = Bass.BASS_StreamCreateFile(songcard.Filename, 0L, 0L, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT); BassMix.BASS_Mixer_StreamAddChannel(_Mixer1, _channel1, BASSFlag.BASS_MIXER_DOWNMIX | BASSFlag.BASS_STREAM_AUTOFREE)
I do use a few BASS_ChannelSetSync, but not using BASS_ChannelRemoveSync (must I use remove?) A try / catch don't help me here, so the app crashes, any ideas? Versions of dlls: Bass.NET 2.4.7.3 Bass 2.4.7.1 BassWASAPI 0.0.0.8 BassMix 2.4.5.0 /Ken
|
|
|
|
|
Logged
|
|
|
|
|
radio42
Posts: 4012
|
 |
« Reply #933 on: 26 Jun '11 - 20:33 » |
Quote
|
How have you declared used the SYNCPROC? It seems, that BASS is trying to invoke on a callback, which was already garbage collected in your code. So you need to make sure, that at any time a SYNCPROC might be invoked your callback delegate still exists.
You do not nesseccarily have to remove a sync, as it will be freed, when the channel is freed - but any callback must still exist up until that time!
|
|
|
|
|
Logged
|
|
|
|
|
ken
Posts: 630
|
 |
« Reply #934 on: 27 Jun '11 - 08:31 » |
Quote
|
How have you declared used the SYNCPROC?
declared SYNCPROC as private (top of the class) and I instance it before ChannelSetSync, but now I moved instance of SYNCPROC to the constructor of the class, and just reuse it. this problem occurs rarely, but when it does app crash...
|
|
|
|
|
Logged
|
|
|
|
|
radio42
Posts: 4012
|
 |
« Reply #935 on: 27 Jun '11 - 09:11 » |
Quote
|
Sounds like a race condition, eg. your class is being garbage collected (and as such your SYNCPROC member as well) before the stream is actually freed. So what are you doing in your destructor of your class? The only reason for a 'CallbackOnCollectedDelegate' exception is, that the callback delegate is already garbage collected but still used by BASS.
|
|
|
|
|
Logged
|
|
|
|
|
ken
Posts: 630
|
 |
« Reply #936 on: 27 Jun '11 - 13:14 » |
Quote
|
So what are you doing in your destructor of your class?
parts of my "player class" public class AudioEnginePlayback { private int _channel1 = 0; private int _P1sync1 = 0; private int _P1sync2 = 0; private SYNCPROC _TrackSync;
public AudioEnginePlayback() { _TrackSync = new SYNCPROC(OnTrackSync); }
public void LoadTrack(LoadMediaClass Track) { Bass.BASS_StreamFree(_channel1); _channel1 = Bass.BASS_StreamCreateFile(Track.Filename, 0L, 0L, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT); BassMix.BASS_Mixer_StreamAddChannel(Track.Mixer1, _channel1, BASSFlag.BASS_MIXER_DOWNMIX | BASSFlag.BASS_STREAM_AUTOFREE);
_P1sync1 = Bass.BASS_ChannelSetSync(_channel1, BASSSync.BASS_SYNC_POS, Track.MixPos, _TrackSync, new IntPtr(0)); //MixCue _P1sync2 = Bass.BASS_ChannelSetSync(_channel1, BASSSync.BASS_SYNC_END, 0, _TrackSync, new IntPtr(1)); //End of File
}
private void OnTrackSync(int handle, int channel, int data, IntPtr user) {
Console.WriteLine("OnTrackSync: " + user.ToInt32());
//top secret stuff here ;-) } }
I think I code it by the "rules", or? /Ken
|
|
|
|
|
Logged
|
|
|
|
|
radio42
Posts: 4012
|
 |
« Reply #937 on: 27 Jun '11 - 13:44 » |
Quote
|
Yes and No. Might it be possible within your app, that an actual instance of your 'AudioEnginePlayback' class might get disposed and garbage collected - but the 'track' is still playing? If yes, it might be possible, that your 'AudioEnginePlayback' gets garbage collected whereas the SYNCPROC is still being used by BASS - resulting in the exception! To be sure you might implement an IDisposbale pattern to your class and make sure the track is freed and removed! E.g. add something like this to your class: ... private bool disposed = false; ... public void Dispose() { Dispose(true); GC.SuppressFinalize(this); }
private void Dispose(bool disposing) { if(!this.disposed) { // remove _channel1 from the mixer! .... // and free the stream Bass.BASS_StreamFree(_channel1);
disposed = true; } }
~AudioEnginePlayback() { Dispose(false); }
|
|
|
|
|
Logged
|
|
|
|
|
ken
Posts: 630
|
 |
« Reply #938 on: 27 Jun '11 - 14:50 » |
Quote
|
Yes and No. Might it be possible within your app...
AudioEnginePlayback should not be disposed, I don't do it manually anywhere. But I try to add Dispose in my class. Thanks!
|
|
|
|
|
Logged
|
|
|
|
|
radio42
Posts: 4012
|
 |
« Reply #939 on: 27 Jun '11 - 15:35 » |
Quote
|
Even if you don't dispose the class manually, it will be disposed and as such subject to garbage collection when you don't keep any reference to your instance any longer.
|
|
|
|
|
Logged
|
|
|
|
|