Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for ALAC #1

Closed
stephen opened this issue Jan 21, 2014 · 124 comments
Closed

Support for ALAC #1

stephen opened this issue Jan 21, 2014 · 124 comments

Comments

@stephen
Copy link
Owner

stephen commented Jan 21, 2014

Currently only supports PCM data; no ALAC support yet.

For AirSonos users: You can work around this on OS X by selecting the system audio instead of direct output from iTunes or AirFoil. You can do this by alt+clicking the volume icon in the top bar, or going through Sound Output in System Preferences.

OS X Volume Icon:
screen shot 2014-11-25 at 10 21 31 pm

Or via System Preferences:
screen shot 2014-11-25 at 10 21 51 pm

@stephen
Copy link
Owner Author

stephen commented Apr 22, 2014

For what it's worth, OS X + iOS all seem to support PCM just fine - iTunes (directly, rather than via system audio) is the only thing I've come across thus far that refuses to perform without ALAC.

@stephen
Copy link
Owner Author

stephen commented May 5, 2014

See openairplay/node_airtunes#22

@auchenberg
Copy link

Looks like Aurora.js can be used in a node-context via https://www.npmjs.org/package/av, which has ALAC decoder available.

Might be useful.

@stephen
Copy link
Owner Author

stephen commented Aug 18, 2014

@auchenberg Funnily enough, the only issue on that repo (audiocogs/alac.js#9) is one I posted 6 months ago asking about usage in node.

I unfortunately don't have the bandwidth to play with this for now- but, if you're interested in experimenting with this, it would be amazing!

@auchenberg
Copy link

I was looking into the Sonos use-case and Sonos seem to support ALAC and ACC, so I'm wondering if the mp3 encoding via lame simply could be removed?

NodeTunes would simply then open a stream of what-ever which Sonos can connect to?

@stephen
Copy link
Owner Author

stephen commented Oct 26, 2014

Definitely a possibility. Previously, I had thought that mp3 was the only codec that Sonos would allow streamed, but I was proven wrong, at least for the case of PCM streaming: stephen/airsonos#26

@auchenberg
Copy link

I wonder if we could detect the stream type, and if it's ALAC send it to Sonos as an experiment?

@stephen
Copy link
Owner Author

stephen commented Oct 26, 2014

Am thinking the same - there's a patched nicercast here that directly writes out PCM - we can try a similar approach with just ALAC.

Am currently away from my Sonos setup until Monday, but I'll try to find some time to test then.

@auchenberg
Copy link

Yeah, that might be an option too, but I think we can bypass the local encoder completely, and simply forward it to the Sonos device, as it supports the codecs natively.

I'm away from my Sonos the next weeks, so I'll give it a stab once I'm back. Do you know how do detect the codec from the input stream?

@stephen
Copy link
Owner Author

stephen commented Nov 1, 2014

Played with this today. I think the data that comes out of the RTP stream isn't usable as is - all I got was static out the Sonos end. Trying to listen by pointing a browser at the stream (i.e. http://localhost:8000/listen), quicktime was also unable to decode the audio, so I figure there's some additional work missing here.

Here's a dump of the the data piped from nodetunes -> Sonos (with some HTTP headers mixed in): https://gist.github.com/stephen/91cb68f5c244b3ac8ce4

@auchenberg
Copy link

Interesting. I'm still away from my Sonos setup, but I'll dig into it once I'm back.

@auchenberg
Copy link

Okay, I had some time last night, and tried piping the nodetunes stream through ffmpeg via fluent-ffmpeg, and got this: `ffmpeg exited with code 1: pipe:0: Invalid data found when processing input``, so it looks like the stream is not a "clean" audio stream, but mixed with something else.

I'm not a stream expert, but my thinking was to pass the stream through ffmpeg, as it supports almost every codec, convert it to MP3, and stream it back via nicercast. A simple replacement of LAME with FFMPEG.

@stephen
Copy link
Owner Author

stephen commented Nov 5, 2014

@auchenberg - What's the command you're running ffmpeg with?

I think we might have been incorrectly decrypting the audio before:

A gotcha: AES works by encrypting 16-byte chunks and the remaining bytes are not encrypted.

from https://github.com/lperrin/node_airtunes#audio-streaming

I'm playing with this modified rtp handler: https://gist.github.com/stephen/34811f240eecbed329a4 which decrypts as 16 byte blocks and leaves the last block untouched.

@auchenberg
Copy link

Aha. Quick and dirty index.js from nicercast: https://gist.github.com/auchenberg/6bbc521fa68398e29e7d

Still getting an error happened: ffmpeg exited with code 1: pipe:0: Invalid data found when processing input, so I might do something completely wrong with ffmpeg

@stephen
Copy link
Owner Author

stephen commented Nov 6, 2014

Yep, getting the same thing for now.. dumping a slice of the rtp stream, the first 16 bytes look like a header (https://gist.github.com/stephen/35f750ea03b3d52167a3). Getting rid of it doesn't help though. I'm also thinking we might not be able to play the output directly, if ALAC requires a container format (e.g. an mp4 container) to play?

@auchenberg
Copy link

Hmmh. With my FFMPEG hack MP3 isn't working either, so I think the stream from nodetunes needs to be wrapped somehow. Do you know what the received stream consists off? Header + data?

@auchenberg
Copy link

I just had a look at other AirTunes implementations and your are right. The first 16 bytes are encrypted for ALAC. See this port of shairport in Java https://github.com/bencall/RPlay/blob/master/src/AudioBuffer.java#L219

When piping the inputStream to ffmpeg, ffmpeg can't read the stream, so I think the root problem is in the RTP layer.

@barcar
Copy link

barcar commented Mar 4, 2015

Spotify also seems to be affected by this issue - Trying to use AirTunes to send to AirFoil fails with the same error. Sadly the System Audio workaround results in new mail notifications and other system noises being sent.

@pabloav
Copy link

pabloav commented Mar 13, 2015

I do wonder about how accurate the theory that Sonos supports streamed ALAC is. See this thread with Sonos support where they post the same chart shown above, but end up concluding that only mp3/aac/wma are supported (as HTTP streams). If so the ffmpeg approach will be safest.

@aspergatus
Copy link
Contributor

I have added this alac-lib: https://github.com/stephank/node-libalac
But I have not tested it yet, will do it this evening: https://github.com/aspergatus/nodetunes

@auchenberg
Copy link

This is interesting @aspergatus. Did you manage to get a working ALAC stream from the server that you could decode? I tried passing it to decoders,and they all choked.

@aspergatus
Copy link
Contributor

I now managed to get some data our of the decoder. But after 2-3 sucessful decoding, I then get an error. I will ask @stephank for help stephank/node-libalac#1

@auchenberg
Copy link

Thats cool, great work!

@stephank
Copy link
Contributor

Oh! I actually wrote that lib because I was trying to integrate it with nodetunes.

But I think the implementation is broken. I don't remember the specifics, only that I fundamentally misunderstood how the encoder works. To get that lib functional probably means a change in API.

I don't think I'll be able to find the time to fix it up, though. Feel free to use it as a starting point and hack it up.

@microadam
Copy link
Contributor

Any luck with getting this to work? Would be useful for something I am working on, so happy to lend a hand if you could point me in the right direction?

@aspergatus
Copy link
Contributor

I tried to get audiocogs/alac.js#11 work, but somehow I don't get the decoding correctly. When I have more time to look at that again, I would compare the encoding and decoding process in details, as well as comparing the input pcm -> encoded alac -> decoded pcm to figure out where the error is.

@buholzer
Copy link

I am getting audio skips, looks like the cpu usage is higher with alac than it was with pcm.
Have to investigate more.

@vkoi81
Copy link

vkoi81 commented Oct 17, 2015

@twentworth12
Did you replace the entire ALAC directory with the one from @jakaru?
That's what I did and then ran npm install libilac followed by running make from within the codec directory. Trying to run make from libilac directory have me a message that said no files available to run make.
I'm sorry but would you mind sharing the steps you took on the pi?

Thanks.

@vkoi81
Copy link

vkoi81 commented Oct 17, 2015

I also tried replacing the endionportable.c file that's inside the codec directory and then ran make from inside the codec directory as that is where I saw the make file.
My pi is still crashing. I'm running raspbian Jessie, not sure if that matters.

@twentworth12 @buholzer @jacaru

@vkoi81
Copy link

vkoi81 commented Oct 17, 2015

I was able to get this to work. I reinstalled airsonos and now I have no issues playing from ios9.

Thanks to everyone!!!!

@dsarel10
Copy link

Does anyone the cause of this error I'm getting, after following tiberiumihai's instructions? I'm running Ubuntu 14.04 with node 0.12.4.

Searching for Sonos devices on network...


/usr/local/lib/node_modules/airsonos/node_modules/bluebird/js/main/promise.js:677
            throw e;
                  ^
Error: Method Not Allowed
    at maybeWrapAsError (/usr/local/lib/node_modules/airsonos/node_modules/bluebird/js/main/util.js:70:12)
    at /usr/local/lib/node_modules/airsonos/node_modules/bluebird/js/main/promise_resolver.js:41:50
    at /usr/local/lib/node_modules/airsonos/node_modules/sonos/lib/logicalDevice.js:112:20
    at done (/usr/local/lib/node_modules/airsonos/node_modules/sonos/node_modules/async/lib/async.js:126:15)
    at /usr/local/lib/node_modules/airsonos/node_modules/sonos/node_modules/async/lib/async.js:32:16
    at /usr/local/lib/node_modules/airsonos/node_modules/sonos/lib/logicalDevice.js:106:22
    at done (/usr/local/lib/node_modules/airsonos/node_modules/sonos/node_modules/async/lib/async.js:126:15)
    at /usr/local/lib/node_modules/airsonos/node_modules/sonos/node_modules/async/lib/async.js:32:16
    at /usr/local/lib/node_modules/airsonos/node_modules/sonos/node_modules/async/lib/async.js:251:17
    at done (/usr/local/lib/node_modules/airsonos/node_modules/sonos/node_modules/async/lib/async.js:126:15)
    at /usr/local/lib/node_modules/airsonos/node_modules/sonos/node_modules/async/lib/async.js:32:16
    at /usr/local/lib/node_modules/airsonos/node_modules/sonos/node_modules/async/lib/async.js:248:21
    at /usr/local/lib/node_modules/airsonos/node_modules/sonos/node_modules/async/lib/async.js:572:34
    at /usr/local/lib/node_modules/airsonos/node_modules/sonos/lib/events/volumeListener.js:24:14
    at Listener.<anonymous> (/usr/local/lib/node_modules/airsonos/node_modules/sonos/lib/events/listener.js:123:9)
    at Request.self.callback (/usr/local/lib/node_modules/airsonos/node_modules/sonos/node_modules/request/request.js:129:22)

@microadam
Copy link
Contributor

I have updated the dependency tree on my version of nodetunes to contain the raspberry pi fix, so for those that are having issues; you should be just be able to point at that, and not have to start messing around with replacing directories and rerunning make

On 18 Oct 2015, at 04:07, ds notifications@github.com wrote:

Does anyone the cause of this error I'm getting, after following tiberiumihai's instructions? I'm running Ubuntu 14.04 with node 0.12.4.

Searching for Sonos devices on network...

/usr/local/lib/node_modules/airsonos/node_modules/bluebird/js/main/promise.js:677
throw e;
^
Error: Method Not Allowed
at maybeWrapAsError (/usr/local/lib/node_modules/airsonos/node_modules/bluebird/js/main/util.js:70:12)
at /usr/local/lib/node_modules/airsonos/node_modules/bluebird/js/main/promise_resolver.js:41:50
at /usr/local/lib/node_modules/airsonos/node_modules/sonos/lib/logicalDevice.js:112:20
at done (/usr/local/lib/node_modules/airsonos/node_modules/sonos/node_modules/async/lib/async.js:126:15)
at /usr/local/lib/node_modules/airsonos/node_modules/sonos/node_modules/async/lib/async.js:32:16
at /usr/local/lib/node_modules/airsonos/node_modules/sonos/lib/logicalDevice.js:106:22
at done (/usr/local/lib/node_modules/airsonos/node_modules/sonos/node_modules/async/lib/async.js:126:15)
at /usr/local/lib/node_modules/airsonos/node_modules/sonos/node_modules/async/lib/async.js:32:16
at /usr/local/lib/node_modules/airsonos/node_modules/sonos/node_modules/async/lib/async.js:251:17
at done (/usr/local/lib/node_modules/airsonos/node_modules/sonos/node_modules/async/lib/async.js:126:15)
at /usr/local/lib/node_modules/airsonos/node_modules/sonos/node_modules/async/lib/async.js:32:16
at /usr/local/lib/node_modules/airsonos/node_modules/sonos/node_modules/async/lib/async.js:248:21
at /usr/local/lib/node_modules/airsonos/node_modules/sonos/node_modules/async/lib/async.js:572:34
at /usr/local/lib/node_modules/airsonos/node_modules/sonos/lib/events/volumeListener.js:24:14
at Listener. (/usr/local/lib/node_modules/airsonos/node_modules/sonos/lib/events/listener.js:123:9)
at Request.self.callback (/usr/local/lib/node_modules/airsonos/node_modules/sonos/node_modules/request/request.js:129:22)

Reply to this email directly or view it on GitHub.

@scotty92fr
Copy link

many thanks microadam, but I have tried modifying the package.json to point to your nodetunes.git but the airsonos show the sonos room, bur no sound comes out the speaker with no error message

@shining01
Copy link

it works on raspberry pi 2 model b with the modification of @microadam. But i get the sound only on one sonos box. i have two sonos in stereo mode. After a few seconds (e.g. 30s) the sound stagnate for a milli second. that repeats sometimes. After e.g. 1 minute sound breaks completely. No sound is comming out.

@skippster
Copy link

Thanks @microadam

I can now get audio but I get a glitch every few seconds. I have tried overclocking the pi2 to 900 and it makes no difference.

Any ideas anyone??

@microadam
Copy link
Contributor

Not tried nodetunes on a raspberry pi, but it's quite possible that the ALAC decoding is quite CPU intensive, so a pi might just not be powerful enough for it. Node is single threaded, so it won't be able to take advantage of the multi cores.

On 18 Oct 2015, at 17:31, skippster notifications@github.com wrote:

Thanks @microadam

I can now get audio but I get a glitch every few seconds. I have tried overclocking the pi2 to 900 and it makes no difference.

Any ideas anyone??


Reply to this email directly or view it on GitHub.

@shining01
Copy link

the cpu usage is on raspberry pi 2 between 50% and 75% on cpu 1. I hope you can optimize it please.
Thanks

@microadam
Copy link
Contributor

I doubt there is much that can be done in terms of optimisation of the ALAC decoding. The decoder is provided by apple, so I imagine it's already pretty optimal.

On 18 Oct 2015, at 18:23, shining01 notifications@github.com wrote:

the cpu usage is on raspberry pi 2 between 50% and 75% on cpu 1. I hope you can optimize it please.
Thanks


Reply to this email directly or view it on GitHub.

@shining01
Copy link

Thanks Adam for the clarification

@microadam
Copy link
Contributor

Having said all that, I could very well be wrong :) past my abilities though I am afraid!

On 18 Oct 2015, at 19:46, shining01 notifications@github.com wrote:

Thanks Adam for the clarification


Reply to this email directly or view it on GitHub.

@shining01
Copy link

But there is one Thing that i realised. ALAC exists since 2004. on the Last OS X 10.10 Yosemite airsonos Works very well on raspberry pi 2. i Hope there is anywhere an optimization possible. Thanks

@luxio
Copy link

luxio commented Oct 18, 2015

Thx @tiberiumihai, your instructions #1 (comment) works well with OS X 10.11.

@buholzer
Copy link

Update for the raspberry users, I had the skips / glitches as described by @skippster in #1 (comment).

Updated my Raspberry Pi 2 Model B to the following configuration:

  • Raspbian GNU/Linux 8.0 (jessie)
  • Node v4.2.1

Do not have any audio skips / glitches anymore and cpu usage is about 50%-60%.

@skippster
Copy link

Thanks @buholzer.
Confirmed no skips/glitches after upgrading from Node 0.10 to 4.2.1

@vkoi81
Copy link

vkoi81 commented Oct 19, 2015

+1,,,everything works flawlessly on Raspbian v8 - Jessie and Node 4.2.1
No skips, decent CPU.

Thanks everyone!!!

@shining01
Copy link

Thanks @buholzer.
Confirmed no skips/glitches after upgrading from Node 0.10 to 4.2.1 and update from debain 7 to 8.
Thanks a lot to all of you guys

@jacaru
Copy link

jacaru commented Oct 20, 2015

We are lucky to get by with 60% CPU use and it all depends on what other stuff the raspberry is doing in the background.

There are three relatively CPU intensive tasks the airsonos package does as a whole:

  1. Decrypt RTP stream (this is likely the most intensive I think)
  2. Decode ALAC
  3. Encode MP3

3 is done in the thread pool, out of the event loop, and that's good. There can be some contention between 1 and 2 which run in the main event loop. Probably moving 2 to the thread pool can improve things a bit on some marginal situations.

@scotty92fr
Copy link

I have tried again on my Raspberry model B with overclocking to maximum and updated node to 4.2.1, it works very well, I just lose the first 25 second at the beginning of the connection. thanks @microadam and everyone you save my Raspberry !

@ponywhite
Copy link

@stephen, please. When will you release a new version of AirSonos which works with El Capitan and iOS9??? It’s a pain in the ass trying to follow all the advices that are posted here. We’re just waiting for you, dude!

@jsalceda
Copy link

Thanks @tiberiumihai. I followed your instructions and it works perfect.
My system is:

  • Macbook running OS X El Capitan10.11.1, and iTunes 12.3.1.23
  • iPhone 6 with iOS 9.1
  • iPad Air with iOS 9.1.

Thanks a lot !

@OlzKennett
Copy link

Hey, this is some great work... I have a problem though. I'm blind so using the command line to fix airsonos is a little difficult, I was wondering if there was a way of going through finder on mac instead to edit thecode? I'm kinda green when it comes to such things so forgive my stupidity... I'd really like to get this working,, mainly so I can get my play 1s working with my apple tv, as I'm sure you can understand, good sound is very important to me. Thanks in advance. O

@OlzKennett
Copy link

I managed to find the file and change the line within finder, should that work or does it need to compile again or something? it seems to call another package with the replaced line sowill this just happen when I type airsonos in terminal?

I could just wait for the package update I guess. :)

@tiberiumihai
Copy link

Make sure the file is saved after the dependency is changed.

After you've changed the nodetunes dependency you will have to type the command:

npm install

into airsonos directory to update the airsonos dependencies.

After doing that you should be able to use airsonos from terminal.

Cheers!

@OlzKennett
Copy link

Bang on, thanks so much, thought there would be a step missing Now working very nicely, though dropping out a little but I think that’s just my isp.

Thanks again.
Oliver
07989945386

On 1 Nov 2015, at 17:19, tiberiumihai notifications@github.com wrote:

After you've changed the nodetunes dependency you will have to type the command:

npm install

into airsonos directory to update the airsonos dependencies.

After doing that you sould be able to use airsonos from terminal.

Cheers!


Reply to this email directly or view it on GitHub #1 (comment).

@jelockwood
Copy link

@microadam

With regards to decoding ALAC being CPU intensive. I am by no means a programmer myself but my understanding is that ALAC decoding should not be excessively CPU intensive as that was the specific goal when Apple originally designed it. Remember the original implementation of ALAC dates back to the original iPod which of course in modern terms has an incredibly feeble processor. ALAC encoding on the other hand might be more CPU intensive but not decoding. Supposedly the main difference between FLAC and ALAC is that ALAC is supposed to be less demanding to do decoding than FLAC. (Both produce similar size files and of course identical quality files.)

If you are decoding a PCM stream and then re-encoding it to ALAC to send to Sonos then this might be the issue as this is then contrary to the comments here not decoding ALAC but rather encoding to ALAC.

Now what may also be applicable is where the ALAC library your using comes from. Originally ALAC was closed source and the first third-party code to process ALAC was done by reverse engineering ALAC by David Hammerton. It is quite likely this original source was nowhere near as optimised as Apple's then private code. More recently Apple of course did make ALAC open source and published the code on macosforge.org. It is quite likely any ffmpeg or similar ALAC libraries pre-date Apple making ALAC open-source.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests