Strange compile errors...

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

no_signal wrote: c:\vstsdk\vstsdk2\source\vstxsynth2\event.cpp(45) : error C2039: 'getNextNote' : is not a member of 'EventQueue'
Thats because it is called 'getNextEvent' in your class declaration, but 'getNextNote' in your definition.
So how can I do this ? I tryed to define the struct as public or static struct ... but than I get lot's of errors.
You could investigate using the queue template, and have a class for note events. Do you really need the EventQueue class? You could do this:

header:

Code: Select all

#ifndef NoteEventQueue_h
#define NoteEventQueue_h

#include <iosfwd>

namespace std {
	template<typename T, class U = deque<T> > class queue;
}

class NoteEvent;

typedef std::queue<NoteEvent> NoteEventQueue;

class NoteEvent 
{
public:
	NoteEvent(int time, int note, int velocity)
		: time_(time), note_(note), vel_(velocity) {}

	int time() const { return time_; }
	int note() const { return note_; }
	int velocity() const { return vel_; }

	void setTime(int t) { time_ = t; }
	void setNote(int n) { note_ = n; }
	void setVelocity(int v) { vel_ = v; }

private:
	int time_;
	int note_;
	int vel_;
};

std::ostream& 
operator<<(std::ostream &os, const NoteEvent &e);

#endif /* NoteEventQueue_h */
Implementation / test:

Code: Select all

#include <queue>
#include <memory>
#include <iostream>
#include "NoteEventQueue.h"

using namespace std;

ostream& 
operator<<(ostream &os, const NoteEvent &e)
{ 
   return os << "Note<t = " << e.time() << ", n = " 
      << e.note() << ", v = " << e.velocity() << ">"; 
};

int main(int argc, char* argv[])
{
	auto_ptr<NoteEventQueue> pq(new NoteEventQueue);

	pq->push(NoteEvent(0, 10, 20));
	pq->push(NoteEvent(40, 50, 60));

	cout << pq->front() << endl;
	pq->pop();

	pq->push(NoteEvent(70, 80, 90));

	cout << pq->front() << endl;
	pq->pop();

	cout << pq->front() << endl;
	pq->pop();

	return 0;
}
Last edited by texture on Wed Aug 04, 2004 7:26 pm, edited 1 time in total.

Post

no_signal, have the struct either outside of the class or as a public inside the class. If using the latter, other must use

Code: Select all

EventQueue::Note_Event nextNote = m_eventQueue->getNextNote();
or whatever.
The "c:\vstsdk\vstsdk2\source\vstxsynth2\event.cpp(45) : error C2039: 'getNextNote' : is not a member of 'EventQueue'" is due to that you haven't declared that method in the class definition (in the header-file)
Stefan H Singer
Musician, coder and co-founder of We made you look Web agency

Post

Havang said that, your queue class does have the advantage that you return the item being popped from the queue, so it might be worthwhile. Implement the class in terms of deque instead of list though.

Post

texture wrote:Havang said that, your queue class does have the advantage that you return the item being popped from the queue, so it might be worthwhile. Implement the class in terms of deque instead of list though.
Hi. i don't really understand your post. can you be more specific ?
Thanks!
A.F.

Post

stefancrs wrote:no_signal, have the struct either outside of the class or as a public inside the class.
Yea, I made the struct outside the class, made some changes and it compiles fine now. Thanks.
A.F.

Post

no_signal wrote:
texture wrote:Havang said that, your queue class does have the advantage that you return the item being popped from the queue, so it might be worthwhile. Implement the class in terms of deque instead of list though.
Hi. i don't really understand your post. can you be more specific ?
Thanks!
A.F.
Not sure which bit. I'll try and explain the bits that might not make sense.

> I don't know what 'Havang' means! :?

> The std::queue class doesn't have functionality to read the item being popped simultaneously - queue::pop returns void. It would be useful if there was a pop function on the queue that also returned the item (e.g. T queue::pop()).
To be honest though, this is not as efficient as reading and popping seperately (depeding upon how good at optimizing your compiler is). It also requires that classes have properly implemented a copy constructor or an assignment operator (or that the compiler-generated ones are ok).

> You could implement a new queue template of your own. It is probably a good idea to follow the stl example and write the queue class 'in terms of' the deque container.
Implementing a class 'in terms of' another class implies either aggregating the class (having it as a member) or privately inheriting from the class.
Private inheritance means that you inherit the implementation of a class, but not its class interface (protected or public member functions, and you never have protected or public member variables, do you?!).

e.g.

Code: Select all

#include <deque>

template <typename T>
class Queue : private std::deque<T>
{
public:
	T pop_front() {
		T f = baseT::front();
		baseT::pop_front();
		return f;
	}

	void push_back(const T& t) {
		baseT::push_back(t);
	}

private:
	typedef std::deque<T> baseT;
};
Everything in deque becomes private in Queue, so you can offer a completely different interface. You'd probably want to add other functions to the interface, such as resize() (for efficiency reasons), empty() and iterator typedefs. Depends what you want from it.

There are not many situations where private inheritance is preferable to containing another class.
You might find it easier to just do it using aggregation.
Last edited by texture on Thu Aug 05, 2004 7:40 pm, edited 2 times in total.

Post

By the way, giving a bit mmore thought to how you might actually use the class, std::priority_queue might be a better option, so that the queue is prioritised based upon time.

Post

I finished my EventQueue class, and I want to make a instance of it named midi_queue instatiated from VstXSynth::initProcess ().

So I did in initProcess () :
midi_queue = new EventQueue();

The problem is that I have another class VAlloc (also instantiated in initProcess () ), and I want to be able to access midi_queue from VAlloc.
The compiler gives this error : 'midi_queue' : undeclared identifier.
I tryed to declare midi_queue as public,protected ... I cannot compile it.
What I want to do, is to pass midi events from processEvents() to EventQueue.
Than in the process replacing call VAlloc::render(sampleFrames);
This render() will look in the list if/how many events are pending for time 'sampleFrames' and update voices.
So how to make it able to see midi_queue from VAlloc class ?
Thanks,
A.F.

Post

There are a number of ways you could skin this cat.

Simply pass midi_queue as a parameter of the VAlloc::render() function.

Alternatively, you could have a member of VAlloc that is a pointer to an EventQueue, and aquaint the Queue with the class - have a function like:
aquaintQueue(EventQueue& q);
Or you could do this in the constructor of VAlloc, and initialise a reference to the Queue (I think this is the cleaner way). You do need to be careful not to delete the queue. If you need to be able to delete the queue, and for the VAlloc class to realise, then some sort of smart pointer would be needed.

Or, you could make the EventQueue class a singleton.

e.g.

Code: Select all

#include <iostream>
using namespace std;

class EventQueue
{
public:
	static EventQueue& instance();
	void doSomething();

private:
	EventQueue();
	EventQueue(const EventQueue&);
	EventQueue& operator=(const EventQueue&);

	static EventQueue *theInstance_;
};

EventQueue* EventQueue::theInstance_ = 0;

EventQueue::EventQueue() 
{
}

EventQueue&
EventQueue::instance()
{
	if (!theInstance_) {
		theInstance_ = new EventQueue();
	}

	return *theInstance_;
}

void 
EventQueue::doSomething()
{
	cout << "Something" << endl;
}

int main(char argc, char* argv)
{
	EventQueue& theQueue = EventQueue::instance();

	theQueue.doSomething();

	return 0;
}
You can get at the sole instance of the queue through the static 'instance' function. Notice that you cannot instantiate the class normally, because the constructor is declared as private.
You can get at it from anywhere in your program then.

Post

Thanks for the reply texture!
I'm not sure I understand the code, but I'll try harder.
Best regards,
A.F.

Post

Basically, what you are doing with the singleton pattern is to limit the creation of your objects, and to also offer a way to get global access to it - anyone can call EventQueue::instance(). It's a really useful technique.

By having a static function that is a class-factory, you can create objects of the class without having to have any in existance already. Objects may only be constructed by the class itself, or by any friends of the class, which makes this solution more robust - in this example, you can only do it through the instance() function.

In instance(), you check to see if the object has been created yet. If it hasn't been, then you create it. There is only one pointer to the instance, and this must be accesible from the static factory function, which means that it must also be static. You need to initialise the static member, which you'd do in the implemenation file, with:

EventQueue* EventQueue::theInstance_ = 0;

The "= 0" isn't actually neccesary - if it is ommitted, then the member will still be initialised to zero. I think it aids readability to include it though.

You also want to prevent copying and assignment, so these are also private, but not implemented.

Post

I have seen something like your singleton example in the VST SDK. I think it's a good option, because I want to be able to access EventQueue from everywhere in my code. Thanks.

Post Reply

Return to “DSP and Plugin Development”