Re: Development Question

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Okay, i tried with the docs. This is what i came up with, however i can't 
seem to be able to play anything more than the first event, like time was 
not moving, Perhaps i've missed something simple to make the time start?

I have pretty much followed everything that's there 
http://www.alsa-project.org/alsa-doc/alsa-lib/seq.html
but no luck

What i am missing here? I guess it's something simple but i can't find

Thanks a lot for the support!

/*
all:
	g++ midi_receiver.cpp -o AlsaNoteTest -lasound
*/

#include <stdio.h>
#include <alsa/asoundlib.h>
#include <vector>
#include <iostream>
#include <unistd.h>

// --------- declaration -------------
namespace AlsaNotePlayer
{
void  findDevices ();
void  openDevice (int client, int port);
void  closeDevice ();
void noteOn_seq(int channel, int note, int velocity, int tick);
void noteOff_seq(int channel, int note, int velocity, int tick);
void play();
void setTempo(int tempo);
}

// -------- definition ----------------

int main()
{
AlsaNotePlayer::findDevices();
AlsaNotePlayer::openDevice(128, 0); // replace by your ports as needed

AlsaNotePlayer::setTempo(60);

int time=0;
int duration = 200;

AlsaNotePlayer::noteOn_seq(1, 60, 127, time);
time += duration;
AlsaNotePlayer::noteOff_seq(1, 60, 0, time);

AlsaNotePlayer::noteOn_seq(1, 62, 127, time);
time += duration;
AlsaNotePlayer::noteOff_seq(1, 62, 0, time);

AlsaNotePlayer::noteOn_seq(1, 60, 127, time);
time += duration;
AlsaNotePlayer::noteOff_seq(1, 60, 0, time);

AlsaNotePlayer::noteOn_seq(1, 59, 127, time);
time += duration;
AlsaNotePlayer::noteOff_seq(1, 59, 0, time);

AlsaNotePlayer::play();
usleep(999999999);

}

namespace AlsaNotePlayer
{

class MidiDevice
{

public:

int client, port;
char* name;

MidiDevice(int client_arg, int port_arg, const char* name_arg)
{
  client = client_arg;
  port = port_arg;
  name = (char*)name_arg;
}

};

std::vector<MidiDevice> devices;

struct MidiContext
{
		snd_seq_t* sequencer;
		int queue;
		snd_seq_addr_t address;
		int port;
		snd_seq_port_subscribe_t *subs;
};

struct MidiContext MidiContext;
snd_seq_addr_t address;

void noteOn_seq(int channel, int note, int velocity, int tick)
{
	snd_seq_event_t event;

	snd_seq_ev_clear(&event);

	event.queue  = MidiContext.queue;
	event.source = MidiContext.address;

	snd_seq_ev_set_subs(&event);
	snd_seq_ev_set_source(&event, MidiContext.port);
	//snd_seq_ev_set_direct(&event);
	snd_seq_ev_set_noteon(&event, channel, note, velocity);
	snd_seq_ev_schedule_tick(&event, MidiContext.queue, 0, tick );

	snd_seq_event_output(MidiContext.sequencer, &event);

       std::cout << "pending events size: " << 
snd_seq_event_output_pending(MidiContext.sequencer) << std::endl;
}

void noteOff_seq(int channel, int note, int velocity, int tick)
{
	snd_seq_event_t event;
	snd_seq_ev_clear(&event);

	event.queue  = MidiContext.queue;
	event.source = MidiContext.address;

	snd_seq_ev_set_subs(&event);
	//snd_seq_ev_set_direct(&event);
	snd_seq_ev_set_noteoff(&event, channel, note, velocity);
        snd_seq_ev_schedule_tick(&event, channel, 0 /*absolute*/, tick );

	snd_seq_event_output(MidiContext.sequencer, &event);

       std::cout << "pending events size: " << 
snd_seq_event_output_pending(MidiContext.sequencer) << std::endl;
}


void play()
{
        snd_seq_start_queue(MidiContext.sequencer, MidiContext.queue, 0);

        int output = snd_seq_drain_output(MidiContext.sequencer);

	if(output == 0) std::cout << "all events drained" << std::endl;
	else if(output > 0) std::cout << output << "bytes remaining" << std::endl;
	else if(output < 0)
	{
		 fprintf (stderr, "Error: (%s)\n", snd_strerror (output));
	}
}

void findDevices()
{
	snd_seq_client_info_t* clientInfo;

	if (snd_seq_open(&MidiContext.sequencer, "default", SND_SEQ_OPEN_OUTPUT, 0) 
< 0)
	{
		return;
	}

	snd_seq_client_info_alloca(&clientInfo);
	snd_seq_client_info_set_client(clientInfo, -1);

	// iterate through clients
	while (snd_seq_query_next_client(MidiContext.sequencer, clientInfo) >= 0)
	{
		snd_seq_port_info_t* pinfo;

		snd_seq_port_info_alloca(&pinfo);
		snd_seq_port_info_set_client(pinfo, 
snd_seq_client_info_get_client(clientInfo));
		snd_seq_port_info_set_port(pinfo, -1);

		// and now through ports
		while (snd_seq_query_next_port(MidiContext.sequencer, pinfo) >= 0)
		{
			unsigned int capability = snd_seq_port_info_get_capability(pinfo);

			if ((capability & SND_SEQ_PORT_CAP_SUBS_WRITE) == 0)
			{
				continue;
			}

			int client  = (snd_seq_port_info_get_addr(pinfo))->client;
			int port    = (snd_seq_port_info_get_addr(pinfo))->port;

			std::cout << client << ":" << port << " --> " << 
snd_seq_port_info_get_name(pinfo) << std::endl;
			devices.push_back( MidiDevice(client, port, 
snd_seq_port_info_get_name(pinfo)) );

		}

	}

	if (snd_seq_set_client_name(MidiContext.sequencer, "Aria") < 0)
	{
		return;
	}

	MidiContext.address.port = 
snd_seq_create_simple_port(MidiContext.sequencer, "Aria Port 0", 
SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_APPLICATION);
	MidiContext.address.client = snd_seq_client_id (MidiContext.sequencer);
	MidiContext.queue = snd_seq_alloc_queue (MidiContext.sequencer);

	snd_seq_set_client_pool_output (MidiContext.sequencer, 1024);
}

void setTempo(int tempo_arg)
{
// argument is not yet considered
        snd_seq_queue_tempo_t *tempo;
        snd_seq_queue_tempo_alloca(&tempo);
        snd_seq_queue_tempo_set_tempo(tempo, 1000000); // 60 BPM
        snd_seq_queue_tempo_set_ppq(tempo, 48); // 48 PPQ
        snd_seq_set_queue_tempo(MidiContext.sequencer, MidiContext.queue, 
tempo);
}

void openDevice(int client, int port)
{
	address.client = client;
	address.port = port;

	snd_seq_port_subscribe_alloca(&MidiContext.subs);

	snd_seq_port_subscribe_set_sender(MidiContext.subs, &MidiContext.address);
	snd_seq_port_subscribe_set_dest(MidiContext.subs, &address);

	snd_seq_subscribe_port(MidiContext.sequencer, MidiContext.subs);
}

void closeDevice()
{
	snd_seq_port_subscribe_alloca(&MidiContext.subs);
	snd_seq_port_subscribe_set_sender(MidiContext.subs, &MidiContext.address);
	snd_seq_port_subscribe_set_dest(MidiContext.subs, &address);

	if (snd_seq_unsubscribe_port(MidiContext.sequencer, MidiContext.subs) < 0)
	{
		return;
	}
	//snd_seq_port_subscribe_free(MidiContext.subs);
}


}



>From: Pieter Palmers <pieterp@xxxxxxx>
>To: "M. Gagnon" <fire_void@xxxxxxxxxxx>
>CC: alsa-devel@xxxxxxxxxxxxxxxxxxxxx
>Subject: Re:  Development Question
>Date: Sun, 18 Mar 2007 11:29:32 +0100
>
>M. Gagnon wrote:
>>This is interesting, Pieter, however my app already has the knowledge of 
>>notes and events, the only reason i had midi bytes was because i converted 
>>the events into bytes because then i could make them play using a single 
>>function on mac.
>>
>>Apparently on Linux/Alsa it's not this way, so i should probably learn how 
>>to put a serie of events in a sequence and then play it. The most recent 
>>sample of this i found was dated '2002' and didn't work, and my own 
>>attempts with the documentation didn't either.
>>
>>I am already able to send events directly. Where can i find recent 
>>infomation on how to schedule them in a queue and play them after?
>I found the doxygen docs that come with alsa-devel sufficient.
>
>What you have to do is convert your own 'events' into ALSA seq events, and 
>then use the snd_seq_event_output function. Things as timestamps etc... are 
>properties of ALSA seq events, and can be set using snd_seq_event_* 
>functions.
>
>
>Pieter
>
>PS: One tricky thing if you use multiple ports is that the port an event 
>should be sent to is also a property of the event.
>

_________________________________________________________________
Windows Live Spaces: partagez vos photos avec vos amis! 
http://spaces.live.com/?mkt=fr-ca


-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Alsa-devel mailing list
Alsa-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.sourceforge.net/lists/listinfo/alsa-devel

[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux