添加到具有由不断变化的值确定的属性的对象向量

发布于 2024-11-29 22:22:27 字数 5188 浏览 1 评论 0原文

对于这个问题,我做了研究,但我不确定我是否一直在寻找正确的术语?也许有人可以提供帮助...

我正在 openframeworks 中编写一个应用程序,它基本上是一个声音可视化工具。我想做的是让程序在某个点创建并绘制一个矩形,其高度由矩形创建时的音频输入频率决定。然后,我希望程序在它旁边绘制另一个矩形,其高度由那一刻的频率决定,依此类推。 (我还计划每次将其平移到左侧,以便创建一个很长的矩形链)。 这些矩形看起来像建筑物(绘制城市景观),所以我创建了一个具有非常简单属性的类:位置、高度等,主要工作(如果我错了,请纠正我)是将位于应用程序的主要部分。 我遇到的问题是绘制物体,然后使其高度与频率相对应。另外,我不希望矩形的高度在创建后发生变化,所以我很难正确地做到这一点。现在,我只能创建一个大矩形,它随着声音输入而上下闪烁。 我不完全确定应该如何每秒向向量添加一个具有正确属性的对象,并使该对象的属性实例保持静态。 我不确定我是否正确地提出了正确的问题,但也许有人可以提供帮助?

这是应用程序代码的顶层:

#include "testApp.h"

//--------------------------------------------------------------
void testApp::setup(){

    ofSetFrameRate(60);
    ofBackground(0,30,60);

    //sound stream setup and such
    ofSoundStreamSetup(0,2,this, 44100, BUFFER_SIZE, 4);
    left = new float[BUFFER_SIZE];
    right = new float[BUFFER_SIZE];

    FFTanalyzer.setup(44100, BUFFER_SIZE/2, 1);
    FFTanalyzer.peakHoldTime = 15; // hold longer
    FFTanalyzer.peakDecayRate = 0.95f; // decay slower
    FFTanalyzer.linearEQIntercept = 0.9f; // reduced gain at lowest frequency
    FFTanalyzer.linearEQSlope = 0.01f; // increasing gain at higher frequencies
    numOctaves=1;


    //control panel setup
    panel.setup("control", 770, 0, 300, 150);
    panel.addPanel("fft settings", 1, false);
    panel.setWhichPanel("fft settings");
    panel.addSlider("Number of Sub Octaves","NUM_OCT",  1, 1,12, false);

    //set up buildings
    for (int i = 0; i <  bldgs.size() ; i+= 20){

    }

}

//--------------------------------------------------------------
void testApp::update(){
    panel.update();
    if(numOctaves != panel.getValueI("NUM_OCT")){
        numOctaves = panel.getValueI("NUM_OCT");
        panel.setValueI("NUM_OCT", numOctaves,0);
        FFTanalyzer.setup(44100, BUFFER_SIZE/2, numOctaves);
    }



}

//--------------------------------------------------------------
void testApp::draw(){

    panel.draw();
    static int index=0;
    float avg_power = 0.0f;

    /* do the FFT   */
    myfft.powerSpectrum(0,(int)BUFFER_SIZE/2, left,BUFFER_SIZE,&magnitude[0],&phase[0],&power[0],&avg_power);


    for (int i = 0; i < (int)(BUFFER_SIZE/2); i++){
        freq[i] = magnitude[i];
    }
    FFTanalyzer.calculate(freq);
    float binDrawWidth = (ofGetWidth()-20)/FFTanalyzer.nAverages;



//float bldgHeighTemp;
for (int i = 0; i <  1000 ; i+=30){
    for (int f = 0; f < (int)(BUFFER_SIZE/2); f++){
        bldg temp;

        freqs[i] = freq[f]*-6;
        temp.bldgPosX = i;
        temp.bldgPosY = ofGetHeight()/2;
        temp.bldgWidth = 30;
        temp.bldgHeight = freqs[i];
        temp.draw();

        bldgs.push_back(temp);
    }
}






}

//--------------------------------------------------------------
void testApp::keyPressed(int key){

}

//--------------------------------------------------------------
void testApp::keyReleased(int key){

}

//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button){
    panel.mouseDragged(x,y,button);
}

//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){
    panel.mousePressed(x,y,button);
}

//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button){
    panel.mouseReleased();
}

//--------------------------------------------------------------
void testApp::windowResized(int w, int h){

}
//--------------------------------------------------------------
void testApp::audioReceived     (float * input, int bufferSize, int nChannels){
    // samples are "interleaved"
    for (int i = 0; i < bufferSize; i++){
        left[i] = input[i*2];
        right[i] = input[i*2+1];
    }
}

[edit] testapp.h

#ifndef _TEST_APP
#define _TEST_APP


#include "ofMain.h"
#include "fft.h"
#include "FFTOctaveAnalyzer.h"
#include "ofxControlPanel.h"
#include "bldg.h"

#define BUFFER_SIZE 512

class testApp : public ofBaseApp{

    public:
        void setup();
        void update();
        void draw();

        void keyPressed  (int key);
        void keyReleased(int key);
        void mouseMoved(int x, int y );
        void mouseDragged(int x, int y, int button);
        void mousePressed(int x, int y, int button);
        void mouseReleased(int x, int y, int button);
        void windowResized(int w, int h);

        void audioReceived  (float * input, int bufferSize, int nChannels);

        ofxControlPanel  panel;
        int numOctaves;


        FFTOctaveAnalyzer FFTanalyzer;

        float * left;
        float * right;
        int     bufferCounter;
        fft     myfft;

        float magnitude[BUFFER_SIZE];
        float phase[BUFFER_SIZE];
        float power[BUFFER_SIZE];
        float freq[BUFFER_SIZE/2];

        vector <float> freqs;
        vector <bldg> bldgs;
};

#endif

不起作用的是它没有创建对象的单个实例和/或每个实例的属性根据频率不断变化,这不是我想要实现的行为;我想要的是每个对象都在一定的高度创建并保持这种状态,然后在它旁边创建一个新的对象,依此类推,就像每秒左右一样。

有道理吗?我仍在努力弄清楚如何提出正确的问题。 谢谢, 布莉

For this issue, I have done research, but I am not sure I have been searching for the right terms? Maybe someone can help...

I am writing an app in openframeworks that is basically a sound visualizer. What I am trying to do is have the program create and draw a rectangle at a certain point, the height of which is determined by the frequency of audio input at the moment of the rectangle's creation. Then, I want the program to draw another rectangle next to it, the height of which determined by the frequency at THAT moment, so forth and so on. (I am also planning to pan this to the left every time, so that it is creating a very long chain of rectangles).
The rectangles are going to look like buildings (drawing a city scape as it goes), so I have created a class of them with very simple attributes: position, height, etc. and the main work (correct me if I am wrong) is going to be in the main part of the application.
The problems I have been having are in the drawing of the object and then having its height correspond to a frequency. Also, I don't want the height of the rectangle to change once it is created, so I am having trouble getting that to happen correctly. Right now, I have only managed to create a single large rectangle that flickers up and down with the sound input.
I am not entirely sure how I should be adding to the vector an object with the correct attributes each second and having that instance of the object's property stay static.
I am not sure if I am asking the right questions correctly, but maybe someone can help?

Here is the top level of the app code:

#include "testApp.h"

//--------------------------------------------------------------
void testApp::setup(){

    ofSetFrameRate(60);
    ofBackground(0,30,60);

    //sound stream setup and such
    ofSoundStreamSetup(0,2,this, 44100, BUFFER_SIZE, 4);
    left = new float[BUFFER_SIZE];
    right = new float[BUFFER_SIZE];

    FFTanalyzer.setup(44100, BUFFER_SIZE/2, 1);
    FFTanalyzer.peakHoldTime = 15; // hold longer
    FFTanalyzer.peakDecayRate = 0.95f; // decay slower
    FFTanalyzer.linearEQIntercept = 0.9f; // reduced gain at lowest frequency
    FFTanalyzer.linearEQSlope = 0.01f; // increasing gain at higher frequencies
    numOctaves=1;


    //control panel setup
    panel.setup("control", 770, 0, 300, 150);
    panel.addPanel("fft settings", 1, false);
    panel.setWhichPanel("fft settings");
    panel.addSlider("Number of Sub Octaves","NUM_OCT",  1, 1,12, false);

    //set up buildings
    for (int i = 0; i <  bldgs.size() ; i+= 20){

    }

}

//--------------------------------------------------------------
void testApp::update(){
    panel.update();
    if(numOctaves != panel.getValueI("NUM_OCT")){
        numOctaves = panel.getValueI("NUM_OCT");
        panel.setValueI("NUM_OCT", numOctaves,0);
        FFTanalyzer.setup(44100, BUFFER_SIZE/2, numOctaves);
    }



}

//--------------------------------------------------------------
void testApp::draw(){

    panel.draw();
    static int index=0;
    float avg_power = 0.0f;

    /* do the FFT   */
    myfft.powerSpectrum(0,(int)BUFFER_SIZE/2, left,BUFFER_SIZE,&magnitude[0],&phase[0],&power[0],&avg_power);


    for (int i = 0; i < (int)(BUFFER_SIZE/2); i++){
        freq[i] = magnitude[i];
    }
    FFTanalyzer.calculate(freq);
    float binDrawWidth = (ofGetWidth()-20)/FFTanalyzer.nAverages;



//float bldgHeighTemp;
for (int i = 0; i <  1000 ; i+=30){
    for (int f = 0; f < (int)(BUFFER_SIZE/2); f++){
        bldg temp;

        freqs[i] = freq[f]*-6;
        temp.bldgPosX = i;
        temp.bldgPosY = ofGetHeight()/2;
        temp.bldgWidth = 30;
        temp.bldgHeight = freqs[i];
        temp.draw();

        bldgs.push_back(temp);
    }
}






}

//--------------------------------------------------------------
void testApp::keyPressed(int key){

}

//--------------------------------------------------------------
void testApp::keyReleased(int key){

}

//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button){
    panel.mouseDragged(x,y,button);
}

//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){
    panel.mousePressed(x,y,button);
}

//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button){
    panel.mouseReleased();
}

//--------------------------------------------------------------
void testApp::windowResized(int w, int h){

}
//--------------------------------------------------------------
void testApp::audioReceived     (float * input, int bufferSize, int nChannels){
    // samples are "interleaved"
    for (int i = 0; i < bufferSize; i++){
        left[i] = input[i*2];
        right[i] = input[i*2+1];
    }
}

[edit] testapp.h

#ifndef _TEST_APP
#define _TEST_APP


#include "ofMain.h"
#include "fft.h"
#include "FFTOctaveAnalyzer.h"
#include "ofxControlPanel.h"
#include "bldg.h"

#define BUFFER_SIZE 512

class testApp : public ofBaseApp{

    public:
        void setup();
        void update();
        void draw();

        void keyPressed  (int key);
        void keyReleased(int key);
        void mouseMoved(int x, int y );
        void mouseDragged(int x, int y, int button);
        void mousePressed(int x, int y, int button);
        void mouseReleased(int x, int y, int button);
        void windowResized(int w, int h);

        void audioReceived  (float * input, int bufferSize, int nChannels);

        ofxControlPanel  panel;
        int numOctaves;


        FFTOctaveAnalyzer FFTanalyzer;

        float * left;
        float * right;
        int     bufferCounter;
        fft     myfft;

        float magnitude[BUFFER_SIZE];
        float phase[BUFFER_SIZE];
        float power[BUFFER_SIZE];
        float freq[BUFFER_SIZE/2];

        vector <float> freqs;
        vector <bldg> bldgs;
};

#endif

what isn't working is that it isn't creating single instances of the object and/or each instance's attributes are constantly changing according to frequency, which isn't the behavior I'm trying to achieve; what I want is for each object to be created at a certain height and stay that way, then a new ones created next to it so forth and so on, like every second or so.

Make any sense? I am still trying to figure out how to ask the right questions.
Thanks,
Bree

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

や莫失莫忘 2024-12-06 22:22:27

好吧,据我了解您的问题,您需要这样做,也许这会有所帮助:

尝试将指针存储在您的 bldgs 向量中

vector<bldg*> bldgs;

,并向其中添加新对象,并

    bldg* temp;

    freqs[i] = freq[f]*-6;
    temp->bldgPosX = i;
    temp->bldgPosY = ofGetHeight()/2;
    temp->bldgWidth = 30;
    temp->bldgHeight = freqs[i];

    bldgs.push_back(temp);

从此处删除绘制方法并绘制每个 < code>bldg 在每一帧上。将其添加到您的绘制方法中:

for(int i = 0; i < bldgs.size(); i++)
{
    bldgs[i]->draw();
}

将与绘制不直接相关的所有内容移动到 testApp 的更新方法中将是更好的做法。例如,将您的创建和填充矢量内容移动到更新方法。

Ok as far as I understand your problem you need to do this, maybe this helps:

Try to store pointers in your bldgs vector

vector<bldg*> bldgs;

and add new objects to it with

    bldg* temp;

    freqs[i] = freq[f]*-6;
    temp->bldgPosX = i;
    temp->bldgPosY = ofGetHeight()/2;
    temp->bldgWidth = 30;
    temp->bldgHeight = freqs[i];

    bldgs.push_back(temp);

remove the draw method from here and draw every bldg on every frame. add this to your draw method:

for(int i = 0; i < bldgs.size(); i++)
{
    bldgs[i]->draw();
}

it would be a better practise to move everything not directly related to draw to put in the update method of your testApp. so for example move your creation and filling the vector stuff to the update method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文