Author Topic: WaveForm's DrawGradient draws a line in the middle of form (ugly)  (Read 9721 times)

aybe

  • Posts: 145
When option is disabled, it's fine but there's no more gradient ...

In fact you can circumvent this by inverting ColorLeft & ColorLeft (swap brighter and darker colors)
but it restricts the possibilities and the general look.

Is this a bug ?

Here's a picture : http://img827.imageshack.us/img827/2273/snap6m.jpg

Thanks !

radio42

  • Posts: 4576
No, its not a bug.
Set the "DrawEnvelope" to "False" and it should be gone - as the envelope is what its causing as the envelop is only drawn in a single color.

aybe

  • Posts: 145
Actually it is DrawGradient that causes this, not DrawEnvelope, I insist that it doesn't looks right,
I spent the last two days trying different color schemes to overcome this and I think it's not drawn in the right order.

The envelope does its job, it envelops at the edges, but how come it does ALSO draw a line at 0db ?

So am I still wrong ?

And you tell me i should disable gradients, but I want to use them, lol !

Thanks for your help  :D

radio42

  • Posts: 4576
If you mean the center line - that one is always drawn using the 'ColorLeftEnvelope' in your case.
There is currently no property available to not draw this center line.
But you might set the 'ColorLeftEnvelope' to 'Color.Transparent' if you want to omit this - but that would also hide the envelope as well.
I'll think of adding a property to prevent drawing the center line in a future release.

aybe

  • Posts: 145
Actually I just found out a way with the center line, I use it instead, but I don't draw the envelope.

After hours of trying, I think DrawEnvelope is sort of flawed, if you zoom in a screenshot,
you clearly see that it's all offset by X+1 and also left parts of amplitudes are never drawn. (envelope)

In fact the envelope looks like more a relief than an envelope.

- What I did best
- What could be even better but envelope makes it dirty
- When envelope is same as background, you clearly see the problem

They are all here in the order listed :
http://img163.imageshack.us/gal.php?g=snap8.jpg

While color 2 is visible on highest peaks, it's not at all on lowest peaks, so why isn't the gradient proportional to the height of the peak ?
example : http://www.hagiplan.com/music/slow_music/images/waveform_before.jpg

If you can address some of these issues, that'd be great !

Thank you  ;D

radio42

  • Posts: 4576
I'll take a look, if I can optimize the envelope - the issue with the envelope is, that it draws a single line from the last peak to the next peak and it seems, that the system drawing simply resutls in rounding divergences which leads to the one pixel offset - so I am not sure, if I can change things here.

Regarding the gradient drawing - that actually looks correct and works as designed.
The gradient drawing is a standard system drawing function, it draws a line with linear gradients, which starts with color1 at the 0 line and ends with color2 at maximum. So it is normal/by design, that color1 is used for the lowest peak only (silence), whereas color2 is used for the highest peak only (maximum) - any level in between will be a gradient of these 2 colors.

aybe

  • Posts: 145
Hello,

Been running onto some other issues with WaveForm yesterday,

I finally achieved 60 fps scrolling under WPF, first version was rendering a complete bitmap
which is about 70Mb (1:256 ratio) but you guess it eats up memory pretty fast the more streams you have.
So if I play 4 songs of 7 minutes, that's almost 300Mb !
Even though it's less problematic today, I really wanted to optimize this part as much as I did with scrolling,
so I spent the last two days, creating a 'buffer' which is twice screen width and then I scroll it, and repeat etc ...

Then not to my surprise, it seems that WaveForm doesn't render a frame range properly, according previous and next image.

On BASS C# solution samples there's an example of that but not with a direct scrolling,
the marker position is simply drawn on every update, so the form doesn't scroll but the marker does,
and then a new bitmap is created when the marker reaches the right.

It's not obvious at all on this sample, but on mine it is, as it's a direct scrolling,
so when I display the new region rendered, you clearly see some glitch like the aliasing is not exactly the same.
It becomes obvious to the user that it's not seamless ...

So I was a bit disgusted but I went to investigate again today ...

I did some tests and I think there's a bug or unexpected result if you prefer ...

On this bitmap http://img401.imageshack.us/img401/9281/snap1j.png,
(bitmaps on a WrapPanel)

I did create N stripes that are 256 pixels large, you can clearly see that every time
you render a region, it draws from y = 0 instead of y = last peak, whether or not anti-aliased.
I did account to render frames like 0-500, 501-1000, and not 0-500, 500-1000, etc ..
the results are the same anyway whatever ratio and size ...

I already wanted to stay on that simpler solution of rendering the full big picture first, then using it.
Saving that picture would be a little counter-intuitive as it'd be a few Mb and there's going to be a lot of stripes in the end.

What I do : I use a small picture for a global overview, but I also use a zoomed-in version as well.
It went unacceptable to generate this on the fly, even on software like WaveLab, CPU rises up instantly,
so the decision was made to use a full bitmap, as we talked previously on other threads.

That sends me back to the question I wanted to ask you first, a few days ago :

Can you provide a lower depth for CreateBitmap, like 16, 15 bits per pixel ?
There about 13000 colors in the previous orange stripe I did post ...

I'm asking you this because I already tried FormatConvertBitmap and it went bad, the picture is dithered and the background doesn't look right.
I did create a wave form renderer a while ago that was 4bpp but I don't use it anymore in favor of WaveForm because of course I use BASS with it !

The thing is at 640x480 there's no performance/memory issues, not when 1920*1200 which is my screen resolution.

Do you think the bug I told you above can be addressed soon ?
I will accomoddate for now with huge memory foot-print, till' I find a solution.

Or maybe you have an idea on how you would solve this ?

Thanks  :D
« Last Edit: 5 Sep '10 - 00:51 by aybe »

radio42

  • Posts: 4576
I am affraid I am not really sure what should be wrong in the picture(s) you posted.

Regarding the memory...this all depends on the WaveForm resolution and of course the image you are generating.
Using e.g. a 10ms resolution means, that the level data is kept for every 10ms of the original pcm sample data.

When you say:
Quote
...it seems that WaveForm doesn't render a frame range properly...
In my oppinion it renders it correctly - so I am not sure what you consider incorrectly here.
I more guess, that there is small slice of 'silence' in the original audio - so the evelope always drwas from the lastPeak and never from 0!
The marker in your picture just shows this small slice of 'silence' - so please inspect your original audio at that position!

Also note, that the WaveForm class was not designed for ALL possible puropses - so there might be better approaches for a scrolling waveform - but this then might need to be implemented by yourself.

Quote
Can you provide a lower depth for CreateBitmap, like 16, 15 bits per pixel ?
Currently there are no plans to do so.,
I am also not sure what yiou exactly mean by 15 bits per pixel - do you mean the color depth?
If yes, I guess the only pixelformat to choose from would be 32, 24 or 16.

Code: [Select]
Do you think the bug I told you above can be addressed soon...I am affraid I am still unsure about what bug you are referrring to.
Can you please explain again what bug you mean - as I so far do not see any bug in the WaveForm.
« Last Edit: 5 Sep '10 - 08:29 by radio42 »

aybe

  • Posts: 145
Memory :
It's not the form data that is huge, the created bitmap actually, so my request about yes, having a bitmap depth that's lower than 32 bits, so 24, 16, 15, 8  etc ...
I proposed 15 because it's 32768 colors ... but yes it's quite forgotten today, remembers me the NT4 era ...  ;D

Form :
There are indeed no silences on these parts like you said, I checked many times, it doesn't look like that in Wavelab or whatever else.
I just had an idea while reading your answer, I'll try to render from frameStart - 1 to frameEnd + 1 and do some collage to see whether it vanishes or not; this is the bug I was talking about.

I'll do some tests and tell you how it goes.

Thank you.

aybe

  • Posts: 145
I have created a small test,

http://img196.imageshack.us/img196/7886/snap38.png

On top it's the render bitmap in one shot,
On middle it's the (10) stripes of the above view,
On bottom it's just an extra one so you can see the width of a stripe,

There's indeed an issue when drawing regions and sticking them next to each other; a sudden change which is not so visible at this picture width and ratio
but really visible not to say very annoying, when you scroll through the generated bitmaps with CreateBitmap but at a much lower ratio.

At X=800 you can see that it starts from a low level whereas in the last stripe it's a high level;
The logic I used was to draw from x1 max to x2 min and not the opposite.
And I think logic from max to max should apply to the envelope drawing plus the +1 offset issue as well.

Is this something that can be fixed for you or shall I go and create my own renderer ?

Thanks

Here's the complete code I did :

I have extended WaveForm below, note that it does exactly the same in Forms without the extension.

Code: [Select]
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Un4seen.Bass;
using Un4seen.Bass.Misc;
using Brushes = System.Windows.Media.Brushes;
using Image = System.Windows.Controls.Image;
using Pen = System.Windows.Media.Pen;
using Point = System.Windows.Point;

namespace WpfApplication3
{
    /// <summary>
    ///   Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private readonly WindowInteropHelper _helper;

        public MainWindow()
        {
            InitializeComponent();
            _helper = new WindowInteropHelper(this);
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // Create stripe of dropped file
            var mp3 = @"D:\Desktop\Bob Sinclar - Gym Tonic.wav";
            var stripe = mp3 + ".stripe";
            if (!File.Exists(mp3)) return;
            var bassInit = Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, _helper.Handle);
            if (!bassInit && Bass.BASS_ErrorGetCode() != BASSError.BASS_ERROR_ALREADY) return;

            // Load or render and save peak data
            var waveForm = new WaveForm(mp3);
            waveForm.FrameResolution = 0.001f;
            waveForm.DrawWaveForm = WaveForm.WAVEFORMDRAWTYPE.Mono;
            if (File.Exists(stripe))
            {
                var waveFormLoadFromFile = waveForm.WaveFormLoadFromFile(stripe, true);
            }
            else
            {
                if (waveForm.RenderStart(false, BASSFlag.BASS_SAMPLE_FLOAT))
                {
                    var waveFormSaveToFile = waveForm.WaveFormSaveToFile(stripe, true);
                }
            }

            // Create full render then striped render
            var full = waveForm.CreateBitmapSource(1000, 128, 0, 99999, true);
            var stripe1 = waveForm.CreateBitmapSource(100, 128, 0, 9999, true);
            var stripe2 = waveForm.CreateBitmapSource(100, 128, 10000, 19999, true);
            var stripe3 = waveForm.CreateBitmapSource(100, 128, 20000, 29999, true);
            var stripe4 = waveForm.CreateBitmapSource(100, 128, 30000, 39999, true);
            var stripe5 = waveForm.CreateBitmapSource(100, 128, 40000, 49999, true);
            var stripe6 = waveForm.CreateBitmapSource(100, 128, 50000, 59999, true);
            var stripe7 = waveForm.CreateBitmapSource(100, 128, 60000, 69999, true);
            var stripe8 = waveForm.CreateBitmapSource(100, 128, 70000, 79999, true);
            var stripe9 = waveForm.CreateBitmapSource(100, 128, 80000, 89999, true);
            var stripe10 = waveForm.CreateBitmapSource(100, 128, 90000, 99999, true);
            wrap.Children.Add(new Image { Width = 1000, Height = 128, Stretch = Stretch.None, Source = full });
            wrap.Children.Add(new Image { Width = 100, Height = 128, Stretch = Stretch.None, Source = stripe1 });
            wrap.Children.Add(new Image { Width = 100, Height = 128, Stretch = Stretch.None, Source = stripe2 });
            wrap.Children.Add(new Image { Width = 100, Height = 128, Stretch = Stretch.None, Source = stripe3 });
            wrap.Children.Add(new Image { Width = 100, Height = 128, Stretch = Stretch.None, Source = stripe4 });
            wrap.Children.Add(new Image { Width = 100, Height = 128, Stretch = Stretch.None, Source = stripe5 });
            wrap.Children.Add(new Image { Width = 100, Height = 128, Stretch = Stretch.None, Source = stripe6 });
            wrap.Children.Add(new Image { Width = 100, Height = 128, Stretch = Stretch.None, Source = stripe7 });
            wrap.Children.Add(new Image { Width = 100, Height = 128, Stretch = Stretch.None, Source = stripe8 });
            wrap.Children.Add(new Image { Width = 100, Height = 128, Stretch = Stretch.None, Source = stripe9 });
            wrap.Children.Add(new Image { Width = 100, Height = 128, Stretch = Stretch.None, Source = stripe10 });
            // An extra one to show stripe width
            wrap.Children.Add(new Image { Width = 100, Height = 128, Stretch = Stretch.None, Source = stripe10 });

            Bass.BASS_Free();
        }
    }

    public static class WaveFormExtensions
    {
        public static BitmapSource CreateBitmapSource(this WaveForm waveform, int width, int height, int frameStart,
                                                      int frameEnd, bool highQuality)
        {
            var bitmap = waveform.CreateBitmap(width, height, frameStart, frameEnd, highQuality);
            if (bitmap == null)
                return null;

            var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                                             ImageLockMode.ReadOnly, bitmap.PixelFormat);
            if (bitmapData == null)
                return null;

            var bitmapSource = BitmapSource.Create(width, height, bitmap.HorizontalResolution,
                                                   bitmap.VerticalResolution,
                                                   PixelFormats.Pbgra32, null, bitmapData.Scan0,
                                                   bitmapData.Stride * bitmapData.Height, bitmapData.Stride);

            bitmap.UnlockBits(bitmapData);
            bitmap.Dispose();

            return bitmapSource;
        }
    }
}

<Window
    x:Class="WpfApplication3.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow"
     Loaded="Window_Loaded">
    <Grid>
        <Image
            x:Name="img"
            HorizontalAlignment="Left"
            VerticalAlignment="Top" Stretch="None"  />
        <WrapPanel
            x:Name="wrap"
            Margin="0,129,0,12" />
    </Grid>
</Window>

« Last Edit: 6 Sep '10 - 00:13 by aybe »

aybe

  • Posts: 145
Hello,

I found another issue while using WaveForm,

http://img251.imageshack.us/img251/3953/snap39.png

Why does the middle line rises sometimes ? Is this a bug or not ?  ???
Also, the middle line tends to disappear sometimes depending the height of the bitmap ...

In the mean time, I think I can overcome the issue I talked to you about previously,
by rendering the bitmap 2 pixels larger, one on left, the other on the right;
(well, render the frames present on these pixels) then crop it, it does look seamless now !
(I haven't tested at very low ratios yet but on small images it's perfect)

Regarding memory usage, I think it can be addressed as well by not rendering the whole; if the above works ...

WaveForm is really great and well integrated with BASS, hence why I would like to stick with it (and not take a new path) :D

I've been doing something already with DrawingVisual and RenderTargetBitmap,
even if it looks a little better than WaveForm it's quite slower than your GDI implementation;
and in the end, when well parametered, WaveForm looks not that bad !

So please, tell me you're going to fix this !

Thanks for your help,  ;D

radio42

  • Posts: 4576
Can you please post your settings of the WaveForm parameters you are using as well as a demo track.
The center line is always drawn linear from left to right (so any spikes are not possible) - so I guess it  might be the envelope make it looking that way.

aybe

  • Posts: 145
Here's one example,

http://img801.imageshack.us/img801/1630/snap40.png

I uploaded the "Brothers Vibe - Rainforest.wav" file to your FTP,

Code :

Code: [Select]
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using Un4seen.Bass;
using Un4seen.Bass.Misc;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private readonly Random _random;
        private WaveForm _form;

        public Form1()
        {
            InitializeComponent();
            Closing += Form1_Closing;
            propertyGrid1.PropertyValueChanged += propertyGrid1_PropertyValueChanged;
            SizeChanged += Form1_SizeChanged;
            _random = new Random();
        }

        private void Form1_SizeChanged(object sender, EventArgs e)
        {
            Draw();
        }

        private void Form1_Closing(object sender, CancelEventArgs e)
        {
            Bass.BASS_Free();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            var bassInit = Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, Handle);
            if (bassInit)
            {
                _form = new WaveForm(@"d:\desktop\Brothers Vibe - Rainforest.wav");
                _form.FrameResolution = 0.001f;
                _form.DetectBeats = true;
                _form.BeatLength = 1f;
                _form.DrawBeat = WaveForm.BEATDRAWTYPE.None;
                _form.DrawEnvelope = false;
                _form.DrawGradient = true;
                _form.DrawVolume = WaveForm.VOLUMEDRAWTYPE.None;
                _form.DrawWaveForm = WaveForm.WAVEFORMDRAWTYPE.Mono;
                _form.VolumeCurveZeroLevel = false;
                _form.ColorBackground = Color.Black;
                _form.ColorLeft = Color.Gold;
                _form.ColorLeft2 = Color.Red;
                _form.ColorLeftEnvelope = Color.Red;
                propertyGrid1.SelectedObject = _form;
                var renderStart = _form.RenderStart(false, BASSFlag.BASS_DEFAULT);
                if (renderStart)
                {
                    Draw();
                }
            }
        }

        private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            Draw();
        }

        private void Draw()
        {
            if (_form != null)
            {
                var bitmap = _form.CreateBitmap(pictureBox1.Width, pictureBox1.Height, -1, _form.Position2Frames(5d),
                                                true);
                pictureBox1.Image = bitmap;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            _form.ColorLeft2 = Color.FromArgb(0, 0, _random.Next(256));
            _form.ColorLeftEnvelope = Color.FromArgb(0, 0, _random.Next(256));
            _form.ColorLeft = Color.FromArgb(0, 0, _random.Next(256));
            propertyGrid1.Refresh();
            Draw();
        }
    }
}

You might want to note that these issues happens mainly on very narrow views of the form, not on bigger or complete views (which shows more but in a smaller image).
Pretty much like the issue I reported to you before, for another issue : http://www.un4seen.com/forum/?topic=11097.0

Oh and yes, I understand now what FrameResolution is !
When 0.001 it will be like the min and max peaks are gathered in a region large 44100*0.001 so 44.1 samples,
so trying to render forms finer than that will never show more details as it's the limit, right ?


Thank you  :D

radio42

  • Posts: 4576
Quote
Oh and yes, I understand now what FrameResolution is !
When 0.001 it will be like the min and max peaks are gathered in a region large 44100*0.001 so 44.1 samples,
so trying to render forms finer than that will never show more details as it's the limit, right ?
Yes, that is correct!

I'll take a look to the example you gave me regarding the 'red' spikes...

aybe

  • Posts: 145
Alright thanks !

radio42

  • Posts: 4576
Hi aybe,

I guess I see where the issue is.
I hopefully provide an update tomorrow...

aybe

  • Posts: 145
Great, thank you  ;D

radio42

  • Posts: 4576
A Bass.Net version 2.4.6.7 is out - which should fix your WaveForm gradient drawing issues!

aybe

  • Posts: 145
I am going to try that,

Thanks  :D

radio42

  • Posts: 4576
I just re-uploaded the new version, since in the previous build was an error.
So if you already downloaded the new version - pls re-download it!

aybe

  • Posts: 145
It's alright, whatever bitmap height, the center line remains now !

A few questions, though :
  • Can you allow us to have a distinctive color for the center line ?
  • Do you think you'll address the other issues I mentioned previously ?
    (Envelope offset and issue when creating stripes you glue later)

Thank you !

radio42

  • Posts: 4576
- Envelope offset and issue when creating stripes you glue later
I think this it is not possible to create multiple stripes from different frame ranges and then cut them together.
So I guess this will not be possible.
The envelope offset is also not really possible I am afraid, as the offset is a result of rounding errors, which can not be generally compensated - it really looks like a GDI+ rounding thing to which I have no influence.

- center line in a distince color shouldn't be a huge thing - I am considering this for the next release

aybe

  • Posts: 145
Alright then, thanks for your support  ;D