This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
ManIkWeet's profile picture

[OpenPeripherals] Play 2 (or more) noteblocks at the same time?

Started by ManIkWeet, 01 June 2014 - 12:01 AM
ManIkWeet #1
Posted 01 June 2014 - 02:01 AM
Hi,

I noticed that if I try to play some notes together (say, a high piano and a low bass) it plays them one after another.
Obviously songs exist with multiple notes at the same time, so I am wondering if it's possible to play multiple notes at the same time :)/>

How to reproduce:
Set up computer with noteblock left and noteblock right, have air under noteblock left and stone under noteblock right
Run this program:

block1 = peripheral.wrap("left")
block2 = peripheral.wrap("right")

block1.setPitch(0)
block2.setPitch(24)

block1.triggerNote()
block2.triggerNote()
If you run it, you'll hear the notes firing after eachother, instead of together.

(this only works with OpenPeripherals installed ofcouse :)/>)

Also, I am on Minecraft 1.6.4 if that makes any difference

Thanks in advance!


Edit:
I figured out that I could use the method "playSound" to play any sound I want instantly, without delay so I got my workaround here :)/>
Just a little fiddling with the pitch, but I did that already by looking at the Minecraft source code :D/>
Edited on 01 June 2014 - 01:25 AM
Whitecatblack #2
Posted 01 June 2014 - 03:41 AM
Hi ManlkWeet,

Just through some quick testing, the most consistent way I found to do it, although it may be totally wrong, is to use parallel api.

So changing your code to this should work:

block1 = peripheral.wrap("left")
block2 = peripheral.wrap("right")

block1.setPitch(0)
block2.setPitch(24)

parallel.waitForAny(block1.triggerNote,block2.triggerNote)

The parallel.waitForAny(a,b,c,…) command, in the way it is being used here, will perform all the functions in its arguments (a,b,c, etc.) instantly. So this should trigger as many note blocks as you want simultaneously.

Hope this was helpful,
Whitecatblack
theoriginalbit #3
Posted 01 June 2014 - 04:26 AM
Well since you've got no sleeps or yielding between those lines of code they should play at the same time… if they don't perhaps we do something in OpenP to stop you from doing it (I'll check that now). Otherwise since you say they don't play at the same time, no there is no way to play notes at the same time, there will always be a delay, I am working on a mod that has a note block that you can play up to 5 notes simultaneously, but that may be a little ways off.

EDIT: nope, we don't do anything in OpenP to prevent multiple notes at once.

-snip-
It should be no different with coroutines… coroutines do not run at the same time, and actually according to the logic you have there it will only play block1 as when that finishes the parallel function would stop (since you used waitForAny)
Edited on 01 June 2014 - 02:28 AM
Whitecatblack #4
Posted 01 June 2014 - 04:41 AM
theoriginalbit said:
It should be no different with coroutines… coroutines do not run at the same time, and actually according to the logic you have there it will only play block1 as when that finishes the parallel function would stop (since you used waitForAny)
Since neither argument yields at any time, parallel.waitForAny will run through both functions with unnoticeable delay and then end (since I am not looping it). And parallel.waitForAny only stops before going through all functions if it comes across a yield within one of the functions. Yes, I am kinda using parallel api in a cheaty way, but it does what needs to be done.

Whitecatblack
Edited on 01 June 2014 - 02:42 AM
theoriginalbit #5
Posted 01 June 2014 - 04:49 AM
theoriginalbit said:
It should be no different with coroutines… coroutines do not run at the same time, and actually according to the logic you have there it will only play block1 as when that finishes the parallel function would stop (since you used waitForAny)
Since neither argument yields at any time, parallel.waitForAny will run through both functions with unnoticeable delay and then end (since I am not looping it). And parallel.waitForAny only stops before going through all functions if it comes across a yield within one of the functions. Yes, I am kinda using parallel api in a cheaty way, but it does what needs to be done.

Whitecatblack
true, still no functionally different than invoking the function one after another…
Whitecatblack #6
Posted 01 June 2014 - 04:57 AM
theoriginalbit said:
true, still no functionally different than invoking the function one after another…
Except for the fact that parallel api calls those functions, in order yes, but also very, very fast. Like fast enough that it impossible(?) to hear the difference. For a proof of test, I hooked up 2 more note blocks, so 4 now, to the same setup and played them using parallel api, and they all played at the 'same' time. That's why parallel api is so powerful: it still does everything in order, if that is important for what one is doing, but also does it instantly.

[Edit] Tested again with 12 note blocks now, to fully demonstrate, and same result: all them play together.

Whitecatblack
Edited on 01 June 2014 - 03:14 AM
ManIkWeet #7
Posted 01 June 2014 - 03:30 PM
The parallel API seems to work indeed, I think I will go with using the playSound function though, it's a little bit of figuring out but I can play complete songs with a single noteblock :D/>

Reason to go with Parallel:
You get to see the fancy particle

Reason to go with playSound:
You can set the audible range

Thanks!
Whitecatblack #8
Posted 01 June 2014 - 03:39 PM
ManlkWeet said:
Thanks!
No problem, happy to help. ^_^/>

If you have any other snags with the project, or want to update us on current progress, feel free to respond.

Whitecatblack
ManIkWeet #9
Posted 01 June 2014 - 03:42 PM
ManlkWeet said:
Thanks!
No problem, happy to help. ^_^/>

If you have any other snags with the project, or want to update us on current progress, feel free to respond.

Whitecatblack

I already had a complete player going with IronNoteBlocks from MiscPeripherals, which was basically just a hacked around version of MysticT. Going to remake it, hoping to include support for pause/stop :D/>
Whitecatblack #10
Posted 01 June 2014 - 04:00 PM
ManlkWeet said:
I already had a complete player going with IronNoteBlocks from MiscPeripherals, which was basically just a hacked around version of MysticT. Going to remake it, hoping to
include support for pause/stop :D/>
Sounds cool, good luck.

Whitecatblack
Lyqyd #11
Posted 02 June 2014 - 03:23 AM
I think you're very confused as to how the parallel API works. This:


doThing1()
doThing2()

Will be faster than this:


parallel.waitForAll(doThing1, doThing2)

So I'm not sure why you're thinking the parallel API will make things any quicker. The only potential speed increase is if the method yields internally after queuing an action for another java thread to perform. As far as I'm aware, the functions involved here do not do so.
Whitecatblack #12
Posted 02 June 2014 - 03:37 AM
Lyqyd said:
So I'm not sure why you're thinking the parallel API will make things any quicker. The only potential speed increase is if the method yields internally after queuing an action for another java thread to perform. As far as I'm aware, the functions involved here do not do so.
Well, if I understand how parallel api functions, it goes through the functions without delay/hardly any. So internally, I'm sure parallel would be slower/same speed.

What I am taking advantage of is that there is no delay/hardly any between queuing functions, so note blocks will play at the same time. If I queued one then the next then the next, they would play with slight delay between each.

[Edit] First picture is running 12 note blocks with parallel api:
Spoiler
[Edit] Second picture is playing 12 note blocks directly one after another:
Spoiler

Whitecatblack
Edited on 02 June 2014 - 02:03 AM
CometWolf #13
Posted 02 June 2014 - 10:45 AM
If this is true, it would simply mean that the openP methods do indeed yield. No other explanation makes any sense, as parallel will never be faster than just running the functions outright.
theoriginalbit #14
Posted 02 June 2014 - 10:48 AM
our methods don't yield unless they specifically need to. perhaps someone has made a coding mistake when implementing Note Block integration and accidentally have it yielding… it definitely shouldn't need to.
Edited on 02 June 2014 - 08:49 AM
Bomb Bloke #15
Posted 02 June 2014 - 12:08 PM
I'd initially assumed the note functions were sleeping, but given that you'd said nothing like that was happening, I'd sorta been thinking it might have something to do with the version in use.

Or maybe something to do with this issue. I dunno.