Посоветуйте графическую либу.
сильно тормозит систему при такой отрисовкеА система перестаёт тормозить, если отключить "такую отрисовку"? То есть оставить всё, кроме собственно отрисовки.
Можно рисовать в opengl. Кроссплатформенно и всё такое. Но, может быть, стоит подробнее пояснить алгоритм отрисовки? Он точно сам по себе не требует большого числа действий?
+1 за OpenGL. В 2D по моему там даже проще рисовать, чем в GDI+.
есть ломаная линия х[i]=x[i-1] + 1 y[i]- произвольныая величина не меняющаяся в времени
необходимо каждый интервал времени в канве или окошке рисовать линию из отрезков x[i],y[i] — x[i]+1,y[i] i=n..m
сейчас у меня каждый тик вызывается цикл от n до m и рисуется ломаная.
[quote] сильно тормозит систему при такой отрисовке
А система перестаёт тормозить, если отключить "такую отрисовку"? То есть оставить всё, кроме собственно отрисовки. [/quote]
да
cейчас у меня каждый тик вызывается цикл от n до m и рисуется ломаная.Может стоит рисовать с каким-то fps (50 раз в секунду, например). Всё равно больше не увидишь.
даже на 30fps тормоза идут или мерцание какое-то убогое проскакивает!
а именно спектр звукового файла, как это сделано в виндовом sndrec32.exeЧувак, ты, наверное, удивишься, но это не спектр. :]
чтобы не было мерцания включается двойная буферизация
а какой порядок i?
еще у TeeChart-а была бесплатная версия TeeChart.Lite (может до сих пор есть)
и там, и там был режим шустрого вывода графиков
рисовать линию из отрезков x[i],y[i] — x[i]+1,y[i]Ч0-ч0? Кстати, "ломаная линия" относится к числу худших визуализаций цифрового сигнала.
Двойная буферизация и OpenGL не решают проблем с головой. Просто незачем на экране шириной в тыщу точек рисовать полмиллиона отрезков. В данной задаче алгоритм простой: если нам нужно нарисовать график на экране в прямоугольнике (0,0)-(1000,400 идем в цикле от 0 до 1000, для каждого экранного х определяем какая часть исходных данных попадает в него, для этой части данных находим минимум и максимум, рисуем вертикальную линию от минимума до максимума. Итого 1000 отрезков вместо полумиллиона и красивый график.
Итого 1000 отрезков вместо полумиллионаага. только у нас получится
1000 * [определяем какая часть исходных данных попадает в него, для этой части данных находим минимум и максимум]
в зависимости от кривизны рук автора, это может быть даже еще дольше, так как размер исходных данных 10^6
в зависимости от кривизны рук автора, это может быть даже еще дольше, так как размер исходных данных 10^6Ну так не надо это делать кривыми руками. Тысяча поисков минимума и максимума среди тысячи величин каждый - это можно сделать достаточно быстро.
все равно это будет быстрее, чем рисование полумиллиона отрезков, потому как вывод графики в любом случае тормознее чем проход по малой части массива.
потому как вывод графики в любом случае тормознеевот не факт. там тоже небось оптимизации есть по выводу отрезков, которые в одну точку превратились
вот не факт. там тоже небось оптимизации есть по выводу отрезков, которые в одну точку превратились
Графическая подсистема не знает, что ты рисуешь, а ты знаешь. Тебе куда легче соптимизировать, чем ей.
В одном случае для каждого значения в массиве два сравнения - с максимумом и минимумом, а в другом - вызов процедуры рисования. Первое точно не может быть медленнее.
Да понятно конечно. это я так... пенартурю уже
Прога пишется под Windows Forms и GDI+ сильно тормозит систему при такой отрисовке. поэтому, собственно, и спрашиваю совета про более скоростные решения (кроссплатформенность будет несомненным плюсом!).Умиляешь... Какая кроссплатформенность при завязке на Мастдай?
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class ShowWav {
JFrame frame;
JTextField txtInputFile;
JLabel lblOutput;
final int width = 640;
final int height = 480;
boolean isRunning;
PaintPanel paintPanel;
WavIO wavfile;
int len = 10000;
int di;
public ShowWav {
super;
frame = new JFrame;
frame.setLocationint) (Toolkit.getDefaultToolkit.getScreenSize.getWidth - width) / 2,
(int) (Toolkit.getDefaultToolkit.getScreenSize.getHeight - height) / 4);
frame.setSize(width, height);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Sound Forge v0.0.1");
paintPanel = new PaintPanel;
frame.add(paintPanel, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel;
txtInputFile = new JTextField("test.wav");
buttonPanel.add(txtInputFile);
addButton(buttonPanel, "Load Wav",
new ActionListener {
public void actionPerformed(ActionEvent event) {
wavfile = new WavIO(txtInputFile.getText;
if(wavfile.read {
len = Math.min(len, wavfile.myData.length);
di = wavfile.myData.length/len;
lblOutput.setText("Data Length: "+wavfile.myData.length+" Number of points: "+len);
}
else {
lblOutput.setText("Error reading file");
wavfile = null;
}
}
});
lblOutput = new JLabel("");
buttonPanel.add(lblOutput);
frame.add(buttonPanel, BorderLayout.SOUTH);
frame.setVisible(true);
isRunning = true;
run;
}
private void run {
while(isRunning) {
paintPanel.repaint;
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace;
}
}
}
public void addButton(Container c, String title, ActionListener listener) {
JButton button = new JButton(title);
c.add(button);
button.addActionListener(listener);
}
class PaintPanel extends JPanel {
private static final long serialVersionUID = 6614959466557160031L;
float x, dx;
int k = 1; // scaling
@Override public void paintComponent(Graphics g) {
super.paintComponent(g);
if(wavfile != null) {
g.setColor(Color.BLACK);
dx = 1.0f*frame.getWidth/len;
x = 0;
for(int i = 0; i < len-1; i++) {
g.drawLineint)x, (intgetData(i)*k+height/2 (intx+dx (intgetData(i+1)*k+height/2;
x += dx;
}
}
}
byte getData(int i) {
return wavfile.myData[i*di];
}
}
public static void main(String[] args) {
new ShowWav;
}
}
Класс WavIO не мой, я его честно где-то нашел, поэтому копипастю со всеми комментариями:
//by Evan X. Merz
//www.thisisnotalabel.com
//Example Wav file input and output
//this was written for educational purposes, but feel free to use it for anything you like
//as long as you credit me appropriately ("wav IO based on code by Evan Merz")
//if you catch any bugs in this, or improve upon it significantly, send me the changes
//at evan at thisisnotalabel dot com, so we can share your changes with the world
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class WavIO
{
/*
WAV File Specification
FROM http://ccrma.stanford.edu/courses/422/projects/WaveFormat/
The canonical WAVE format starts with the RIFF header:
0 4 ChunkID Contains the letters "RIFF" in ASCII form
(0x52494646 big-endian form).
4 4 ChunkSize 36 + SubChunk2Size, or more precisely:
4 + (8 + SubChunk1Size) + (8 + SubChunk2Size)
This is the size of the rest of the chunk
following this number. This is the size of the
entire file in bytes minus 8 bytes for the
two fields not included in this count:
ChunkID and ChunkSize.
8 4 Format Contains the letters "WAVE"
(0x57415645 big-endian form).
The "WAVE" format consists of two subchunks: "fmt " and "data":
The "fmt " subchunk describes the sound data's format:
12 4 Subchunk1ID Contains the letters "fmt "
(0x666d7420 big-endian form).
16 4 Subchunk1Size 16 for PCM. This is the size of the
rest of the Subchunk which follows this number.
20 2 AudioFormat PCM = 1 (i.e. Linear quantization)
Values other than 1 indicate some
form of compression.
22 2 NumChannels Mono = 1, Stereo = 2, etc.
24 4 SampleRate 8000, 44100, etc.
28 4 ByteRate == SampleRate * NumChannels * BitsPerSample/8
32 2 BlockAlign == NumChannels * BitsPerSample/8
The number of bytes for one sample including
all channels. I wonder what happens when
this number isn't an integer?
34 2 BitsPerSample 8 bits = 8, 16 bits = 16, etc.
The "data" subchunk contains the size of the data and the actual sound:
36 4 Subchunk2ID Contains the letters "data"
(0x64617461 big-endian form).
40 4 Subchunk2Size == NumSamples * NumChannels * BitsPerSample/8
This is the number of bytes in the data.
You can also think of this as the size
of the read of the subchunk following this
number.
44 * Data The actual sound data.
NOTE TO READERS:
The thing that makes reading wav files tricky is that java has no unsigned types. This means that the
binary data can't just be read and cast appropriately. Also, we have to use larger types
than are normally necessary.
In many languages including java, an integer is represented by 4 bytes. The issue here is
that in most languages, integers can be signed or unsigned, and in wav files the integers
are unsigned. So, to make sure that we can store the proper values
Ужасно кроссплатформенно, будет работать под линуксомна powerpc явно не заработает
Пока не работает на Big-Endian, говорить об "ужасности" не приходится
это java, a там инты вполне big-endian.
И что значит "инты вполне Big-Endian", можешь пояснить?
Пост как бы и был написан не к тому, чтобы опустить этот конкретный код, а чтобы напомнить, что java <=> кроссплатформенность и можно даже без особых ухищрений написать непереносимый код
В интернетах пишут, что «JAVA virtual machine always used big-endian, Intel x86 used little-endian.»
Ну пишут одно, а представленный код будет работать неправильно =)
Оставить комментарий
stilet78
есть необходимость выводить 2D графику, а именно спектр звукового файла, как это сделано в виндовом sndrec32.exe, только мне необходимо скроллить больше 10 секунд ( т.е около полмиллиона отрезков с рефрешем около 50 раз в секунду ). Прога пишется под Windows Forms и GDI+ сильно тормозит систему при такой отрисовке. поэтому, собственно, и спрашиваю совета про более скоростные решения (кроссплатформенность будет несомненным плюсом!).