Thread: Turning off While loop in realtime

  1. #1
    Registered User
    Join Date
    Jan 2010
    Posts
    19

    Turning off While loop in realtime

    Hello all,

    I'm going to ask a question that involves MIDI, but it actually doesn't have to be MIDI. My questions is on how to turn off the while loop via hardware input. (i.e. keyboard)

    I'm trying to write code that begins looping once it receives a MIDI note on message, and turns off when it receives a MIDI note off message. Here's part of the code:

    while(1)
    {
    if(Pm_Poll(stream))
    {
    length = Pm_Read(stream, event, sizeof(long));

    for(i = 0; i < length; i++)
    {
    status = Pm_MessageStatus(event[i].message);
    data1 = Pm_MessageData1(event[i].message);
    data2 = Pm_MessageData2(event[i].message);
    printf("Status: %d, Data1: %d, Data2: %d\n", status, data1, data2);

    }
    int time, temp, loop = 0;
    while(status==144){
    //if(status==144)
    //{
    time = Pt_Time(NULL);
    while(Pt_Time(NULL) - time < 100);
    temp = loop;
    loop = temp+1;
    printf("\n%d\n", loop);
    //}
    if(status != 144) break;
    }
    if(status==128 && data1==67) break;
    }
    What it does now is it just keeps adding 1 to int loop every 100ms once it receives a MIDI note on, which is status 144. (in the second while loop)

    The problem is that once the while loop is initiated, it doesn't update the status. In other words, once status == 144 it begins the loop, and it no longer takes in information which would break the while loop.

    If someone can tell me how I can turn off the while loop after it's been initiated I would greatly appreciate it. Thanks in advance.

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    If you are part way through a loop, or any sequence for that matter, and you aren't continually checking, you can't abort early. The loop will only exit each time it (or you) test the condition. That is to say:
    Code:
    while( test )
    {
        a();
        b();
        c();
    }
    If when b happens, the test condition is now false, it's still going to keep on executing through b and c. The only way around that is:
    Code:
    while( test )
    {
        if( test ) a(); else break;
        if( test ) b(); else break;
        if( test ) c(); else break;
    }
    Unless that's not what you're asking.


    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    Registered User
    Join Date
    Jan 2010
    Posts
    19
    Just did it, but the the loop still doesn't stop once it is initiated:

    Code:
    while(1)
    	{
    		if(Pm_Poll(stream))
    		{
    			length = Pm_Read(stream, event, sizeof(long));
    			
    			for(i = 0; i < length; i++)
    			{
    				status = Pm_MessageStatus(event[i].message);
    				data1 = Pm_MessageData1(event[i].message);
    				data2 = Pm_MessageData2(event[i].message);
    				printf("Status: %d, Data1: %d, Data2: %d\n", status, data1, data2);
    				
    			}
    			int time, temp, loop = 0;
    			while(status==144)
    			{
    				if(status==144)
    				{
    					//int time, temp, loop;
    					time = Pt_Time(NULL);
    					while(Pt_Time(NULL) - time < 100);
    					temp = loop;
    					loop = temp+1;
    					printf("\n%d\nJR", loop); 	
    				}			
    				else break;
    			}
    			if(status==128 && data1==67) break;//this is to exit the program when MIDI note off 67(note G4) is received. 
    		}
    	}
    Is there another way to terminate the while loop by changing the test condition? Or if there are other ways to initiate the increment of int loop, and stop it when note off message (status 128) is received I'd be happy to know.
    Last edited by baikal_m; 04-21-2010 at 07:50 PM.

  4. #4
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485
    Quote Originally Posted by baikal_m View Post
    Is there another way to terminate the while loop by changing the test condition?
    You should be able to use a variable instead of 1 in the while loop, then set it to 0 to terminate.

  5. #5
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by baikal_m View Post
    Just did it, but the the loop still doesn't stop once it is initiated:

    Code:
    while(1)
    	{
    		if(Pm_Poll(stream))
    		{
    			length = Pm_Read(stream, event, sizeof(long));
    			
    			for(i = 0; i < length; i++)
    			{
    				status = Pm_MessageStatus(event[i].message);
    				data1 = Pm_MessageData1(event[i].message);
    				data2 = Pm_MessageData2(event[i].message);
    				printf("Status: %d, Data1: %d, Data2: %d\n", status, data1, data2);
    				
    			}
    			int time, temp, loop = 0;
    			while(status==144)
    			{
    				if(status==144)
    				{
    					//int time, temp, loop;
    					time = Pt_Time(NULL);
    					while(Pt_Time(NULL) - time < 100);
    					temp = loop;
    					loop = temp+1;
    					printf("\n%d\nJR", loop); 	
    				}			
    				else break;
    			}
    			if(status==128 && data1==67) break;//this is to exit the program when MIDI note off 67(note G4) is received. 
    		}
    	}
    Is there another way to terminate the while loop by changing the test condition? Or if there are other ways to initiate the increment of int loop, and stop it when note off message (status 128) is received I'd be happy to know.
    What are the usual values of length? If your 128/67 pair is not the very last one in your array o' messages, then you have no chance of stopping, because you throw the data away long before you get to the if statement. Also, if you ever get in the 144 loop, heaven help you, because there's no way out of that (status cannot change inside that loop).
    Last edited by tabstop; 04-21-2010 at 08:07 PM.

  6. #6
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    status should be declared volatile if it's expected to be changed by something else. Otherwise, you need to actually be changing it some place in your loop; which you don't appear to be doing. Otherwise, why would you expect it to change, if nothing your loop does actually changes it?


    Quzah.
    Hope is the first step on the road to disappointment.

  7. #7
    Registered User
    Join Date
    Jan 2010
    Posts
    19
    All,

    Thanks for the replies. I think there was a confusion with which while loop I was talking about. The following is the only bit of the code we need for this discussion:
    Code:
    		if(Pm_Poll(stream))
    		{
    			length = Pm_Read(stream, event, sizeof(long));
    			
    			for(i = 0; i < length; i++)
    			{
    				status = Pm_MessageStatus(event[i].message);
    				data1 = Pm_MessageData1(event[i].message);
    				data2 = Pm_MessageData2(event[i].message);
    				printf("Status: %d, Data1: %d, Data2: %d\n", status, data1, data2);
    				
    			}
    			int time, temp, loop = 0;
    			while(status==144)
    			{
    				if(status==144)
    				{
    					//int time, temp, loop;
    					time = Pt_Time(NULL);
    					while(Pt_Time(NULL) - time < 100);
    					temp = loop;
    					loop = temp+1;
    					printf("\n%d\nJR", loop); 	
    				}			
    				else break;
    			}
    		}
    Basically, the top part inside the for loop is happening constantly. When I push on my hardware midi controller, it receives the mssage. If the button I push sends out a midi note, it first receives status 144 when I push down, and status 128 when I let go. This part of the code works perfectly fine, and streams whatever midi data I send to the code.

    What I'm trying to do is to start the loop to increment the data int loop within the while loop when status is 144, and stop when status becomes 128. I eventually want to turn this into something that'll repeat a sequence of notes only when I push down on a midi note on the hardware controller.

    So that's why I put the while loop there, to loop and increment. status is being changed anytime there's midi input in the for loop just before the while loop, so I thought that by sending a midi note off(status 128) the while loop would terminate. It doesn't. This is where I have a problem.

    I took out the 128 & 67 line because it's not important. It was there to break out of the first while loop (that has been taken out here) and it worked perfectly fine.

    I would greatly appreciate it if someone is still willing to help!

  8. #8
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Which loop are you trying to break from when the value changes? Because nothing you're doing in the for loop has anything to do with checking to break on 144.

    So, if we assume you mean the while loop, then yes, you either need to change status based on something you specifically change inside the loop some place, or, you need to make it volatile, so that it knows it's being changed by something else.


    Quzah.
    Hope is the first step on the road to disappointment.

  9. #9
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485
    Wouldn't the while loop work on it's own? You could probably do without if(status==144) and the break statement as far as I can tell.

    Code:
    while(status==144)
    {
            //int time, temp, loop;
            time = Pt_Time(NULL);
            while(Pt_Time(NULL) - time < 100);
            temp = loop;
            loop = temp+1;
            printf("\n%d\nJR", loop);
    }
    Last edited by Subsonics; 04-21-2010 at 08:37 PM.

  10. #10
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by baikal_m View Post
    All,

    Thanks for the replies. I think there was a confusion with which while loop I was talking about. The following is the only bit of the code we need for this discussion:

    Basically, the top part inside the for loop is happening constantly. When I push on my hardware midi controller, it receives the mssage. If the button I push sends out a midi note, it first receives status 144 when I push down, and status 128 when I let go. This part of the code works perfectly fine, and streams whatever midi data I send to the code.

    What I'm trying to do is to start the loop to increment the data int loop within the while loop when status is 144, and stop when status becomes 128. I eventually want to turn this into something that'll repeat a sequence of notes only when I push down on a midi note on the hardware controller.

    So that's why I put the while loop there, to loop and increment. status is being changed anytime there's midi input in the for loop just before the while loop, so I thought that by sending a midi note off(status 128) the while loop would terminate. It doesn't. This is where I have a problem.

    I took out the 128 & 67 line because it's not important. It was there to break out of the first while loop (that has been taken out here) and it worked perfectly fine.

    I would greatly appreciate it if someone is still willing to help!
    My hat of guessing is a little rusty, but I'm guessing you're asking "how come my while loop won't break me out of my for loop?" To which the answer is, hey put it inside the for loop. Definitely if you intend to do something with status, you're going have to do it where status is.

    Code:
    		if(Pm_Poll(stream))
    		{
    			length = Pm_Read(stream, event, sizeof(long));
                            int time, temp, loop = 0;			
    			for(i = 0; i < length; i++)
    			{
    				status = Pm_MessageStatus(event[i].message);
    				data1 = Pm_MessageData1(event[i].message);
    				data2 = Pm_MessageData2(event[i].message);
    				printf("Status: %d, Data1: %d, Data2: %d\n", status, data1, data2);
    				if(status==144)
    				{
    					//int time, temp, loop;
    					time = Pt_Time(NULL);
    					while(Pt_Time(NULL) - time < 100);
    					temp = loop;
    					loop = temp+1;
    					printf("\n%d\nJR", loop); 	
    				}			
    				else break;
    			}
    
    		}

  11. #11
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Yes, that's not what I was specifically saying to do. My example would have been more if he had done something like this:
    Code:
    while(status==144)
    {
            //int time, temp, loop;
            if( status == 144 ) break; time = Pt_Time(NULL);
            if( status == 144 ) break; while(Pt_Time(NULL) - time < 100);
            if( status == 144 ) break; temp = loop;
            if( status == 144 ) break; loop = temp+1;
            if( status == 144 ) break; printf("\n%d\nJR", loop);
    }
    And really, the only possible purpose for doing that would be if you IMMEDIATELY needed to stop whatever you were doing the instant status changed to 144. Which again, still would mean you need to make it volatile, because nothing he actually does changes it in the loop itself.


    Quzah.
    Hope is the first step on the road to disappointment.

  12. #12
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485
    Assuming this is correct and have been confirmed.

    Quote Originally Posted by baikal_m View Post
    If the button I push sends out a midi note, it first receives status 144 when I push down, and status 128 when I let go. This part of the code works perfectly fine, and streams whatever midi data I send to the code.

  13. #13
    Registered User
    Join Date
    Jan 2010
    Posts
    19
    Thank you all so much for the suggestions. It seems that I wasn't too clear exactly what I wanted to do... but, I've figured it out and here's the answer to my own question:

    Code:
    		if(Pm_Poll(stream))//status will only change if it re-Polls
    		{
    			length = Pm_Read(stream, event, sizeof(long));
    			
    			for(i = 0; i < length; i++)//if(Pm_Read(data->stream, data->event, sizeof(long)) > 0)
    			{
    				status = Pm_MessageStatus(event[i].message);
    				data1 = Pm_MessageData1(event[i].message);
    				data2 = Pm_MessageData2(event[i].message);
    				printf("Status: %d, Data1: %d, Data2: %d\n", status, data1, data2);
    			}
    			
    			int time, temp, loop = 0, counter = 0;
    			while(status==144)//Enters this while loop if status==144, or noteon
    			{	
    				if(Pm_Read(stream, event, sizeof(long)) > 0)//Events must be detected within the loop as well. Otherwise there's no way out of this while loop
    				{
    					status = Pm_MessageStatus(event[i].message);
    					data1 = Pm_MessageData1(event[i].message);
    					data2 = Pm_MessageData2(event[i].message);
    				}
    
    				time = Pt_Time(NULL);
    				while (Pt_Time(NULL) - time < 1);// set to 1ms because 100ms is too long for Pm_Poll to notice anything has happened
    				counter++;//Every 1ms counter is incremented
    				if(counter % 100 == 0)//when it has counted 100ms, (or whatever you set it to)
    				{
    					loop++;					// it increments loop
    					printf("\n%d\ntest\n", loop); 
    				}
    			}
    		}
    This code does exactly what I wanted it to do. It increments "loop" every 100ms when it receives a noteon message (status 144) and terminates when it receives a noteoff(status 128).

  14. #14
    Registered User
    Join Date
    Feb 2010
    Posts
    244
    use 'break'.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Poll event loop
    By rogster001 in forum C++ Programming
    Replies: 2
    Last Post: 09-17-2009, 04:28 AM
  2. need help with a loop
    By Darkw1sh in forum C Programming
    Replies: 19
    Last Post: 09-13-2009, 09:46 PM
  3. funny-looking while loop
    By Aisthesis in forum C++ Programming
    Replies: 3
    Last Post: 08-30-2009, 11:54 PM
  4. nested loop, simple but i'm missing it
    By big_brother in forum C Programming
    Replies: 19
    Last Post: 10-23-2006, 10:21 PM
  5. loop issues
    By kristy in forum C Programming
    Replies: 3
    Last Post: 03-05-2005, 09:14 AM