Playing 10 tracks in sync.
I am trying to create an audio player which will play 10 wav files simultaneously. I have tried with sfplay~ but the sync is not good especialy when the seek command is used on all 10 tracks.
I was thinking about using buffer~ instead but is there a way to connect the buffers so they will start in sync?
Buffer~ won’t start, they’re buffers. But groove~ will. Use a signal to play and sync several groove~ object together.
What you need to do is use signal rate control of each playback device. In max, control-rate events (float, integer, message, list) have an event priority (read max tutorial 5 for more info) events don’t happen at exactly the same time. So if you start 10 sfplay~ objects from one toggle, they do not all start playing at the same time, which you know!
But if you use a signal based playback object (play~ or index~ and groove~ to an extent) they will stay perfectly in sync with eachother.
Here is a patch that shows what I mean:
----------begin_max5_patcher---------- 1170.3oc2Z00iahCE84jeEHTeZ2oSwewG8GReopZEIXRoBLQAG0Isp429ZrI y5sCAbvfalQZDL3PrO2y8d88X67y0q72T+Dsw26ide1a0petd0JYSsMrp64U 9UoOssLsQ9Z9aqqpnLt+CpOiSehKaeeY5oKMxNVUejWR4xuRPWq40LdSwOns sAfOdo48GnMhNLkWTy9mCzsbEZRPQhWwCjD1dKn6h2W59VEYxQsdy2dOF6qM BrzJ4H3+I5grTV5kOaeJe6WKX6zFhHBosagXYuijCDDnMHB6nfcwL.ss8q0q au7vLPVengWueRLltsilnsiCjFMLRRAgQyusu4HmWy52.AcspZheZOUgJ+Mo rc985jAC4HQ5NR3yWmOigQ+t.EuvOlOr4cE+2Kr57x5TdulMJYpw1cThx+hf ORFx+Bm.kTQaZR2QeAmHFt2AD+MOTS+rRrcrBJPE0CTyvLmrxUBTJKXzy8yH vajQZJ1wRK8eXfjETnk7CRlBggCOqvLxObubu74geTISOLXVEYh7CoaVSjQY UfIkUwoGNeiyZ9aV5UpnBBfJXGELVIUXz.jPLV1MXf7Vrre.nWIjPhJz1DNH dPoCAKLGbUoCzC4BXTdxq4Da6gZlHkHaVEdorIrALjkEmHpQBfRle0GhNXyU igtLkRUcF0tofMLnqiRI8SohtS5t5SfGJvNNFmnn5PmMU9eeddp72QxlxsvQ CWQ.KoxPU3pHOm3Ht7uN68dveB5DkLNcBsjN6tQbVjY6ptNKm1bYnTcxYpqK Ktq9TrjVhVf0kcGPNXKkmtbjyBp7Hh.TJO.iVWkLjDznWCpuzsF7PaCQ7qec T515j2Nlv2nJhFRaCDXGa81QaiNoDXIo7lRkhFw.RrjXbtdiBVF8okrl50pz n13FDdzJMfnotQHg5xThwyOmxq2sqjdiUgJX8WCBDNd7Q2Vk5vcOV3NW94S. X6RaPAcaXx7WQh9irzsmGtlqlkjXP8ShVNd60keiKOjxZJS4TupFulzp8kzl EbmuCsbiKiVP8E8SPaqOx3KeXNwxnb0xtHXmUbPHSJStA9yByb8yMap7RmRz tyGLzYwKEr75gpYFO0iCnrnQ6XAL7e5e8q1wovfNEZwy+wG7mRIht.VKyDWN IEWgb1bLOWrvHI638sZ1txSOlVL2mF0UyPAVlgp1TY.N17TT4aHOSxe6m9gb XZa++yhM0GOr8hEc4z389uAJi1vKXRYnZuT6YWq8ResHKixzqsWUjsuVHYqC DdeoWepoXp8PgGGSgtESIlfoX2hIQoROfI9Nf4Xh.QxvO0OjjHR7yOYKZCMg AQ2FCFgwsS8hD3SbKVnF5xSNAsXaPq9SyQjvXn0wILhQKbL9i3VHgLfkZOv7 6ML0ddW2RNrsXBaBO4345LASsGjkKwDzTemCwjQ0yCbJl.QlDO414BLw0Awt ERAlfIvcnqKvoSOARLES2WgS.2ph1DIAfarXGNRW.CIb1jaALQtEvs4i.SJ4 Pt67oPabo5OYIVCMj8b3DGlrboai8HD0gyE.jrGD+7SVhUij6XQrm3ges9eg z8qoV -----------end_max5_patcher-----------
Actually, groove~ might be more appropriate. It depends on the situation, but groove~ will sound better than play~. Here is one way of syncing groove~ objects together.
----------begin_max5_patcher---------- 706.3oc4XEsbiBBE8YyWAiOmMUTPM6Gx9xNc1gnDCcTHiP5lzNMe6qBZisIZ rQqS6ru.CWH54b3buB44YV1qD6oRavOA+FXY87LKKcnx.VUisryH6iRIR8xr iDYYTtxdtYNEcuRGeaJ4vcRkXa8L7cYhcpTpR+6bphtVvUR1SzxXP2E0gYw5 GhX0C+H.Z2XsbRlds1+hlGS3j541RTQaX7j+jSiTF7iV5T77.g3xV+fxVW3B Gv8m.DiWiGXYrWlMqrYdOodFUJIIzyntjxiAI4BwizifTgXK.NGHUjbU4fKq Gvt0CyJUG1RMby19UZzPp7WdiRENPKRPjoaYnoqMwx8FDKN8uEP7LsJUPhWQ 3IiipneRWTYBFnx3p8R99iuKpEgYGm8HMWRRGZ9iOZfTOvPc73Sc5SwjnicS vlLwoqrcC.8f5NzqsimCVIRRRocaTOyQxJJMdICIdYWbInQkKiyqrcD8b6xV QyaQ4cqhlIhoMG22jPIKgWZaA1qKxtaP+hIz6rWxkhw2pKsxX5o6vWIAcDqb EsonXC833T3pRytnS4lyeQU9GyG.QeFe.T0pKp0Lh2YJZxTuNXiugMdF1Xxx wgekYi602a9FwF30qW4537YwlVxAKRalfDPma8.nFYAB0cdAS1YGpO6o7.Op 6Z7e7Z5cHTna83mU41tlCbr7JUp799KTgCrj9+MBUv.S8LcSnPsZ250E0c0B E3AAOI8vBBa83nYlxyy63dNH+gcXeyUlgnv9WqRuB6TF+8+uA52RY72phRwt 7nZFUeqUvoWTLUpXbhhI3MWD5MKZCKNlxadOgLV7VQwosq.A39Ktm1aLEzGL sbRwDtO5T4GqlRLg5Clve8vD5Ct2gwnE3hTBeOykgOMZRPa3zpfN8ASASJlP 8x86MsXJrOXxcZwT41B7ZXBM8X5p5Db.XpXvKy9G1eMRrC -----------end_max5_patcher-----------
The "seek" message is not the right one for this purpose.
Note the following, from the sfplay~ reference page:
The seek message is intended to allow you to preview and adjust the start and end points of a cue.
NOTE: The seek message is always deferred to low priority.
You want the "preload" message, which looks up and preloads the specified moments and assignes them a cue number, and then you play the audio cues just by sending in the right number.
If you want all your sfplay~ objects to use the same set of cues, see the sflist~ object.
I just did a little test, that seems to show that groove~ and play~ don’t use the same interpolation:
----------begin_max5_patcher---------- 1217.3ocuYksjahCE8Y2eEDd1oKzBKdpJ+F4kLolBCxtYBHQgj6o6jJ9aezB zMtCfwVf7CHjLKGNbum6B+5gM96YuP39d+k2271r4WOrYidI0BaZmuwuJ8kr xTt9v7oj+is+e82Z9KA4EgdYNozCzsJ8TE6jnjHzmBrc0CLpfW7ShZM.7wf1 kMGo30ZhAF96SoG825466881CoHWeOj22Oi76c0noU5Sx+qjl7TZZ2+UmJxd pfd7eZHYByUEABk2Qun.0VzN0VH3wf2tERHWPeCwp098COn1r0NdImWyEoBx 4g4F7MxMETghZNTxR06zNWMLDaArisP5swvoYKvcvVYrpJhB6eft1Wll8Cuu 3crgwdlb9uoMjbO4uu3UWl95ajXYAkjwNQE8sutjYCllY6QRgVZSEFqG.fHM mEsj7zHVUBu8d6WVuM83P1P3c1QOIgywkaAImO84yiIEAtQxgWbjlVNLsDaG s.MNWXnyjhxdR9JdLgnkjYBsjY.ZQ5HryrXpKpIdf.4ukgbFlVrTlADpok3D mYvH7BVpX5WINEFZI2.csHiDBrl7ydBBWr5dTHKkfAFM3jnooGzcPOUmJEE7 xhbRSGNXMExP6ohBFsef3gMf9SemQy7KYpGTySHF0FJ1Hjf68jxIB4ipD6lS P6K4BCENMsl+DSbVIvbC4ubqlOlTBGj3t6HUcgtMoAFOc5MKnvCOsRl0Lqhe dYTeZcs1NIKguSVJLvTSAROjrBRP7Z4MqgwyX0WK78Dgh1eLiUxZ5L+2gAf3 nsirWvfTTv0kZvljgQFRADz+Rc3RDjDmfQfsirmCBu0jR4kxZy7p3dJStRYk vqmC5fVcvj60pynzAMEzlj3rROzrx5mDILxR2QyPH1YYKIUVxMESsDTynkiA uWcJrI+QXfoQHQNKUoB5A1TIJkbWQ5jh4kE7K6Fxb1YXREYIo1k2QxigNhUO QKdlzvUg0rq8Gv6M2abqFugBhBWdCpJBmmdjLPyFo4csHxqjwpktWdbQZiPM w4Z3.KIPParRcpCHrCzp53twcJu+Tr9nn9Ew7C11aCX3zL.IV10Rio30xDCs f8OP0axUrTvdTHXdTXrkQOMoUrFc9cDJb+oCGHMFRbpVw.u2fEiFPEXY.UPa 6egqPDUxOySyNOsBeuGkIqPF09oOzC3vtsqeaGeMqjnq9MX8yZ7NeUBM8OBX r9SBW9jFWgZ3.sB.uu48iKM6GRM9Sz79W39kxArqTtrSMOSlmrznTm9HzQo+ vGfTCI05Wxmb1olrNNo6KS389MJWJcTPequSe68VK16fdpHOmbQeopJxqYET QKH799fucuILAtBlTYLbKXBgwp7JAAwpArLQgtY1h13YvfpRwtIzB0nEFqQa nAs5Yt.sprGb466v4XCF6VLglAlP6bKlfygmPtGSfElm57UiiTCs9B5YVhVz rT6BcJChliGIxsdjpF4dcUB25QNGGRracHgIyU5G3NLEMGyIra4o4XNAcqvk 91EcML4V2tOjSyHXxsIiAWg3fPTqhd3E56gVquqSb4pQibqtEXNhDpOKjKwz rh4biYX2lkJNZWu2p5Y1hV7bpG3FkOBizIW.kkzqfY3t2lYKZmC0Zwaa4je+ v+a+1MOB -----------end_max5_patcher-----------
The output of play~ is precisely why I tend to use index~ whenever I can. Maybe it’s something I’m doing wrong, but groove~ seems to have significantly better interpolation than the other objects. Wave~ isn’t even worth putting in that patch, as it’s intended for very short samples and as such needs not have high-quality interp.
I think the only point in play~ is when you need signal control over the playback position, but also want variable speed playback. If you try that with index~ you just get major aliasing, understandably.
I never want that, so I stick to index~. The interpolation in groove~ is amazing though, even with different playback speeds it’s output looks consistently accurate. It’s just a shame it can’t be controlled at signal rate fully. But then, if it was an easy thing to code an object like that, the cyclists probably would have!
yes, groove~ is quite good, but it has its limitations.
----------begin_max5_patcher---------- 753.3ocyXssbaBCD8Y7WACO1w0itf.Q+P5KcxzACxDxfk7.xsNISx2d0EbrS pbBl3H7KHqUBzYO5rqz5GmEDsTri0EE9iveEFD73rf.iIsgf99AQqy2Uzj2Y lVDm8Wwx6hlaGRx1IMl+1ygfEv8lqKMFUS76H7diqDbIOeMyLzOYsk4778iI 1JaXR48aXVrD0UWwyahBu4nWtq9AyvPvBPu4M4xhaq4U+tkUHsuJBqGNDCh0 MwD8SX1BvKeJ9100b0pY7GzAiVLXrB0FeZ1L8i4W.hAPbwLPeyL.Cy.oPcCA NwLSw8EMrSJa.dlbfYYF9fXjMIwSL4rb6pUr1mC2ER..fCBBRGEAspQjKilq Vfbd0X3oLrlYPzTcisyooInSZBMBZh8PYdwyt3gjn2QwinlbA1r.GddNapfQ f1tMJHzJ5JDaXNAM4jaPG1Sb4OYHC6aicQYI13YzWuLcMqqKuh8e5zFgXiZa NzoDMdTRzwnJww8JQSFNhkWRmrnWUPVoI.yAoLtr9iMbEGaTLvD3QDyYFuNF hQkmQ8Qb4+fKYdqkUEhFQqcRfETBkhhUpwEYwY.j9GXbJhPTN8Q97YbjYp8f .nI0AA3qzcmPWoNdSefIxAuR88kI5YFhIvif8kv5DLSUqP7G0sI14fZR+LTy 7K.IgPF5I4CHI7Ws7QmVRmHOz0MtR7Vx5j9TRlnoDpuTNRQUUCygme5Ciq4x 287Xqmf.Tay9mSTLfBWh1R2w.9tJr9qIhMWpNALFg+ktHLmkYLMzhUvL40l1 WAFDBPtJPENIjCjZxYll8YIGy6E0Tye6evgYo01eMi0I11Vr2K58+vCqdIqS Vyyk0B9QyA8p4bacYIyL7d2bcc4FgJMRODBuw4t2PQDZ.HB6UDQt5PTx.PDw qHhN.Dk5UDouD9GBIpegzPh1zUT5SLEe0sykNDVxuxaDdHXJ4JESvqpsNjey UhfWdANBjsPUuMBZuTLE+RuOKXGRRq23QmGAp57zr+gY6Ur1 -----------end_max5_patcher-----------
so groove~’s interpolation is not ‘ideal’ – what ever that means. there’s probably no such thing as ‘ideal interpolation’, but you can do much better than groove~ (e.g. using sinc interpolation), if you accept higher cpu load.
concerning the noisy output of play~ and wave~, i believe this is not an interpolation issue, as the earlier example only uses original playback speed, i.e. no resampling. i guess this is due to the limited precision (32 bit floats) for the playpack pointer (with groove you only provide playback speed, not the actual position in the buffer~).
when i was experimenting with high quality resampling, i found that using a double precision accumulator inside an external for the playback position yielded much better results than using a signal inlet to let the user provide the playback pos in maxmsp.
i realize that this might not make things any clearer… oh, well…
So does anyone know if groove~ uses cubic interpolation? I’m fairly sure the other objects all use linear of varying qualities. Also, does anyone know of any buffer~ playback externals that use cubic or higher quality interpolation? Is there anything that implements sinc interpolation, or is it really too cpu-intensive to be worthwhile?
Variable-speed playback isn’t something I normally use, but it would be interesting.
^^^^ other than the hr.objects, because I find those a little difficult to use in normal patches…..
they are good though…
@raja, if you don’t care for variable speed playback, then you can safely stick with [index~], as it does no interpolation at all, and thus is friendly to your cpu and sounds fine.
for anyone interested in resampling, here is something to play with:
it is an external similar to groove~, but uses sinc interpolation for the variable playback speed.
this not only gives better quality for upsampling (slower playback -> pitching down), but also for downsampling (faster playback) by mostly eliminating aliasing.
it uses an external library called libresample by dominic mazzoni, which was originally written for audacity.
libresample itself is based on ‘resample’ by J.O.Smith.
resample~.mxo is compiled for osx, but the sources are included.
if someone wants to try this on windows, you’d have to recompile libresample for your platform first.
i haven’t tested this intensively, it was merely a research project for me.
originally i planned to support all features of groove~, but got distracted along the way…
if you find this object useful or come across some bugs (most likely), please drop me a line.