Tips: Managing the Queue in a Soundrop Room

Here are some tricks you can use to get the most out of the time you spend queuing and voting tracks in Soundrop listening rooms.

Spotify Search Syntax Works in Soundrop

You may or may not have discovered that the Spotify client supports complex search expressions. Full details are posted on the Spotify website article Searching Spotify.

What’s cool is that you can use this same syntax inside Soundrop to search the current room’s queue (as well as the Spotify catalog). Briefly:

Search Expression Explanation
artist:Squarepusher Returns all tracks by artist Squarepusher in the room queue followed by Squarepusher tracks in the Spotify catalog.
artist:”Ceephax Acid Crew” Note the use of quotations around arguments containing spaces.
title:Exploding Returns all tracks in the room queue containing the term “Exploding”
title:”Exploding Psychology” Another quoting example.
label:Warp Returns all tracks published on the Warp Records label.
album:”Ground State” Returns tracks on albums entitled “Ground State”
genre:Blues Return all tracks tagged in the Blues genre
artist:Burnside title:Heaven Returns all tracks by artist Burnside containing the word Heaven in the track title.
artist:Yes year:1974 Return all tracks by artist Yes released in 1974.
artist:Yes year:1970-1974 Same as above in the time range 1970-1974.
SpotifyUser Search the current room queue for all tracks queued and voted for by SpotifyUser. e.g. if you’re in a Soundrop room where I hang out and you type my name in the Soundrop search you’ll see everything I’ve queued or voted for. (This is particularly useful).

Credit to friends in the Electronica Room for pointing this out. I’m just writing it down because it’s useful :)

Building and Sharing Ordered Playlists in Spotify

Over the past weekend I collected a bunch of tracks I’ve heard recently on Soundrop and put together a Spotify playlist to share with my friends online. For this specific playlist I wanted to order the tracks so that flowed together seamlessly when gapless / track cross-fade is enabled in the Spotify client.

I collected all the tracks I wanted into a new Spotify playlist, and then re-arranged them into the order I wanted, published the playlist and posted a link to my friends. Empirically, my friends can load the playlist and the tracks are in the correct order. However, they’re not in the correct order on all of the devices I have Spotify installed on.

It seems that before I published the playlist, my other devices (my laptop and phone) synchronized with Spotify and cached the playlist metadata. However, the meta-data that’s cached is not up-to-date and so although all the tracks are present in the playlist on my phone and laptop, they’re not in the correct order. So everyone else except me gets to listen in the intended order >:/

Unfortunately, I don’t see any easy way to force my laptop or phone to re-synchronize. I think this is a bug in Spotify but likely not one they’re going to get fixed immediately. So here’s a simple work-around if you’re interested in building ordered Spotify playlists:

  • In your Spotify settings, set ‘publish new playlists automatically’ to disabled.
  • Create a new playlist called “working”.
  • Drag all the tracks you want in your final playlist into the “working” playlist.
  • Arrange the tracks in whatever order you want in the “working” playlist.
  • When you’re satisfied, create another new playlist with your final title.
  • Drag the entire “working” playlist into the final playlist. DO NOT EDIT the final playlist at all.
  • Delete the “working” playlist.
  • Publish the final playlist and share that link with your friends.

In this way you will get the correct order synchronized on all your devices.

If you’re interested, the playlist I was working on is published here:

LOVE (AlpineLakes Picks from Soundrop Electronica Room – play in order w/max crossfade)

Here’s the intended track order: (note that you can get this by simply selecting all the tracks in the playlist and then Copy & Paste)

HQ Special FX – City / Town Garden Ambience
Isotroph – Crossroads
SCSI-9 – Schaukel Duo – Original Mix
Daso – Go Upstairs
Kosheen – Cover
Nicolas Masseyeff – Mugen
Dennis Ferrer – Son Of Raw
Trifonic – Parks On Fire
Fritz Kalkbrenner – Facing The Sun
Lee Jones – Westworld – Original Mix
Fort Fairfield – Falls Road
Sinewave – Wizard Of Ahhhs
Brothomstates – Mdrmx
Petter – Modern Eternity
Mark Ernestus – Mark Ernestus Meets BBC
Dub Specimen – Journey
Eastern Sun – Rapture At Sea
Marquez Ill – Regret (Vector Lovers Remix) – Vector Lovers Remix
Lawrence – Five Leaves
Eastern Sun – Days Gone By
Floating Points – Myrtle Avenue
Julio Bashmore – Ask Yourself (Midland Remix)
Dominik Eulberg – Der Tanz der Gluehwuermchen
Fort Fairfield – The Dead Sea Scrolls
Beta to the Max – Intergalactic Elevator
The Knife – Silent Shout
Pupkulies & Rebecca – Save Me
Paul Kalkbrenner – Plätscher
Laid Back – Bakerman (Soul Clap Remix) – Soul Clap Remix
Stimming – Una Pena – Original
Mooryc – All those Moments (Marek Hemmann Remix) – Marek Hemmann Remix
Stephan Bodzin – Callisto
Joris Delacroix – Entourloupe
Dinky – Sealed
Dakar – I’ve Got That Feeling – Original
Elton D – Reflection – Hertz Mix
Marmion – Schöneberg – Roberto Rodriguez Piano Edit
SCSI-9 – Had I But Wings Like Thine – Original Mix
Sound Effects – Static

Quick-n-Dirty Apache Setup on Ubuntu

sudu apt-get install apache2

Git – Distributed Is the New Centralized

Of all the version control systems I’ve used to date, by far my favorite has been Perforce. Perforce is very powerful, has excellent support for both command line and rich graphical tools (e.g. graphical branch history and diff tools are fantastic). And for individuals / small teams it’s free.

Currently, every digital asset I care about is stored on my Perforce server (code, documents, photos, and music) and I use it to keep these items cleanly synchronized across OSX, Windows, and Linux devices. This works great for me and is super simple. However, it’s complicated and expensive to securely extend this system to ad-hoc collaboration with people on the Internet who I don’t necessarily know and trust. Enter Git created by Linus Torvalds to address systemic challenges managing the evolution of the Linux kernel source.

The major advantage that Git has over VCS’s like Perforce is that it does not require a centralized server.

Seems you can hardly avoid Git these days. Time for me to make the jump. This post is another public notebook entry with useful links I’m saving off for reference:

In practice:

Big Data Study Links

This is public notebook entry. No original information here. Just links to big data resources on the web and in print that I’m finding useful as I begin to explore the substance behind the monikers and attempt wetware capture.

Currently reading Pete Warden’s Big Data Glossary and it’s a great introduction.

Michael Nielson’s blog post on Consistent Hashing

Julian Browne’s blog post on Consistency, Availability, and Partition Tolerance (CAP)

C/C++ Header Encapsulation

I wrote a nice detailed blog post about ten years ago detailing a systematic and sane way to ensure that your large project collection of C/C++ headers don’t get out of control. Unfortunately, it was published on a blog that no longer exists (I’ve got the database somewhere on a CD but it’s more trouble than it’s worth to go digging for it). It absolutely amazes me how much code exists that absolutely sucks because the authors simply don’t understand C/C++ header encapsulation (or worse just don’t care).

Nothing drives me more nuts than including a header in my code written by someone else and breaking the build. When the build breaks in a case like this one of two things is going on: either there’s an actual error in the header (e.g. a syntax error), or the header’s declaration(s) depend on declarations that you don’t have in scope. Typically it’s the later case as few programmers worth their salt will knowingly give you a header that won’t even compile for them.

So what’s the deal? The deal is typically that the header author declared some stuff in the header in terms of declarations that themselves are not declared in the header you’re including. In other words they took a dependency on declarations included in another header and assumed it was obvious enough that it wouldn’t ever cause anyone any problems.

Here’s a simple example that has some hidden subtleties:

// header_A.hpp
#pragma once
struct A { int a; };

// header_B.hpp (revision 1)
#pragma once
void Foo(A & a_);

Note that as written the function Foo declared in header_B.hpp takes as input a reference to an instance of struct A declared in header_A.hpp. This means that callers of function Foo cannot simply include header_B.hpp in their cpp file and call the function. Instead they must themselves track down the missing dependency and include header_A.hpp.

One might refer to the documentation for function Foo and see that it is declared in header_B.hpp and write a simple skeletal cpp like this to get started:

// client1.cpp (revision 1)
#include “header_B.hpp”
void TryOutFunctionFoo() { /*I’m going to make a call to Foo here and see what it does*/ }

This of course won’t compile because function Foo’s signature depends on struct A which is not in scope in client1.cpp. Where is it struct A declared? The documentation says that struct A is declared in header_A.hpp. Okay, let’s try this:

// client1.cpp (revision 2)
#include “header_B.hpp”
#include “header_A.hpp”
void TryOutFunctionFoo() { /*I’m going to make a call to Foo here and see what it does*/ }

Nope. Same compile error. The order that client1.cpp includes the headers matters so to get this to compile we need this:

// client1.cpp (revision 3)
#include “header_A.hpp”
#include “header_B.hpp”
void TryOutFunctionFoo() { /*I’m going to make a call to Foo here and see what it does*/ }

Okay, now that it compiles we can go ahead and create an instance of struct A, pass a reference to Foo and see what happens. But there’s obviously a problem with header_B.hpp because we all would expect revision 1 of client1.cpp to compile cleanly. Specifically, the author of header_B.hpp should have forward declared struct A:

// header_B.hpp (revision 2)
#pragma once
struct A; // forward declare struct A
void Foo(A & a_);

Or, at least that’s the conventional wisdom and few people will argue with you if you do just that. There are well documented rules for when one should forward declare and include a header in another header and these are widely accepted. Here are several articles that talk about these rules in detail:

In this example the programmer wishing to make a simple call to function Foo still needs to figure out which header struct A is declared in but because of the forward declaration of struct A in header_B.hpp, the order of include no longer matters (i.e all revisions of client1.cpp presented here now compile cleanly). So this is at least an improvement.

Now suppose we add another structure declaration to header_B.hpp as follows:

// header_B.hpp (revision 3)
#pragma once
// struct A; // forward declare struct A
#include “header_A.hpp”
void Foo(A & a_);
struct B : public A { int b; };

You’ll note that we commented out the forward declaration of struct A and replaced it with a nested include of header_A.hpp. This is actually required as the forward declaration will not suffice. The compiler needs to know the size of struct A in order to compile the declaration of struct B (see the links above for all the details – there’s a bit more to it than is presented here).

What’s interesting is that the programmer wanting to make a trivial test call to function Foo can now simply write:

// client2.cpp (revision 1)
#include “header_B.hpp”
void TryOutFunctionFoo() { A a; a.a = 0 ; Foo(a); }

… and it works. Likely they never even stopped to consider where struct A is declared because simply including header_B.hpp got the job done via the nested include of header_B.hpp.

Interestingly, if we had nest-included header_A.hpp in revision 2 of header_B.hpp instead of forward declaring struct A, the programmer writing client1.cpp would not have had to explicitly included header_A.hpp in the original example. For what it’s worth, I prefer nested includes over forward declaration because:

  • I don’t have to waste time tracking down dependencies and explicitly including their declaration headers.
  • I like being able to look at the #include statements and seeing the filenames that I need to look at if I have further questions.

In practice, it seems to work well and I can’t think of any cases where nesting includes instead of forward declaring actually breaks anything. If such cases do exist, I’m sure someone will point it out to me :)

My preference aside, the real point of this article is to talk about the evil that is headers that impose include ordering constraints. Do what you want with regards to forward declarations vs. nested includes.

Headers that impose include order are evil because as projects grow the amount of time you can waste figuring out the magic order required to get the build off the floor can be large. This is actually way more important than it might appear in the trivial examples presented in this article.

How many times have you had to take over code written by someone else to fix a bug or add a feature only to discover that you need to do a little refactoring? Looks simple enough so you tell your boss it will take an hour. And then you get into it and discover that the declarations are so snarled up that if you touch anything the build is on the floor. Or you initiate a new project using a set of unfamiliar libraries and waste hours or days trying to figure out the magic order to include their headers just to get a completely empty project analogous to the simple test client to compile.

Here’s a really simple little trick that ensures that the headers you write do not impose hidden include ordering constraints:

// smoke_test_header_B.cpp
#include “header_B.hpp”

That’s it. Notice that smoke_test_header_B.cpp will not compile if anything declared in header_B.hpp depends on a declaration that has not been brought into scope by either a forward declaration or a nested include. For each header in your project create a simple smoke test wrapper and compile them all. If they don’t compile then you’ve got a problem. If they do, then anyone can include your header without regard to include order and this saves a ton of time.


Thanks to John Sheehan for pointing out that my first revision header example was flawed. I initially presented a simple example in which header_A.hpp declared a structure and header_B.hpp declared a function that took as input a reference to the structure. In this case a forward declaration of the structure declared in header_A.hpp in header_B.hpp would have sufficed. This prompted me to rewrite the example and brought me to the sub-point that I actually prefer nested includes vs. forward declarations – even in cases where a forward declaration is all that’s strictly necessary.

Publishing Previously Unreleased Information About Encapsule Project

My friends, family, and several close business associates know of my quest to create a component software engineering platform based on digital hardware modeling and design metaphors ~10-years ago. Although the effort ultimately failed when I ran out of money and options, I still believe the core concepts are valuable and I’ve long considered publishing the entire project as open source.

Recently I created another blog and Twitter account dedicated to this effort and have started the process of disclosing the previously unreleased details of the project. So far, I’ve just published some screen shots of the prototype and a whitepaper I wrote in 2003 that details the goals, potential applications, and architecture of the platform. Source code is coming at some point in the future.

If you’re interested, check out the Encapsule Project Blog and/or follow the project on Twitter (@encapsule).

Image

Crunching Soundrop’s April Track Numbers

Soundrop, the fantastic social music listening application for the Spotify platform, reported recently that they streamed 35 million tracks in April, 2012 (up from 15 million tracks in March). I was curious about the number and how it relates to the number of people using Soundrop so I did little number crunching and estimate that this equates to ~19.5K active Soundrop users who spend 3-4 hours / day in the application.

Assumptions:

  • 35 million tracks – I assume this is measured by Spotify and corresponds to the number of Spotify clients that stream a particular track as directed by the Soundrop application. In other words, if I’m in the Electronica room with 250 other listeners, each song played is counted as 250 tracks streamed.
  • Having filled large MP3 players to capacity, a reasonable ballpark estimate is 12K tracks is ~1 month’s worth of 24×7 music without a repeat. More detail on this later.
  • My guess (pure speculation actually) is that an average Soundrop user spends 3-4 hours / day in the application. I know it’s a lot more for me but I’m not sure how typical this is. So I’m being a bit more conservative.

Math:

30 (days/month) * 24 (hours/day) * 60 (minutes/hour) = 43.2K (minutes/month)

43.2K (minutes/month) / 3.5 (minutes/track) = ~12.3K (tracks/month)
(i.e. if you have 12.3K tracks of length 3.5 minutes (just an estimate based on my observation of averages) you’ve got ~1 month’s worth of 24×7 music without a repeat)

35M tracks / ~12.3K (tracks/month) = ~2800 (24×7 listeners)
(my guess is that your average Soundrop listener tunes in 3-4 hours/day – this is just an guess)

24 (listening hours/day) / 4 (active listener hours / user day) = 6 (users)
24 (listening hours/day) / 3 (active listener hours / user day) = 8  (users)
(i.e. for every 24-hour period, between 6 and 8 active listeners streaming 3-4 hours/day represent a single 24×7 listener – again a total SWAG)

~2800 (24×7 listeners) * 6 (users) = ~17K monthly users who tune in 4 hours / day on average
~2800 (24×7 listeners) * 8 (users) = ~22K monthly users who tune in 3 hours / day on average

May:

I just pulled out my calculator and added up the listener count displayed in all the public Soundrop listening rooms visible to me and see ~8K people actively listening right now. What will May’s track number be?

My SWAG is 120 million tracks will be streamed in May, 2012.

It will be interesting to see if I’m at all close.

Fun with Spotify & Soundrop

I’ve been a big fan of the Spotify music platform since it launched in the U.S. last year. Spotify hosts a massive online archive of music available for streaming. Wikipedia states that Spotify’s catalog comprised 15-million tracks in July, 2011. According the Spotify website, there is over 80-years worth of HD music in their catalog currently and they’re adding 10K new tracks per day. So a lot of music.

If you’re casually into music, it’s worth checking out as large portions of the catalog are available for free streaming at an acceptably high bit-rate. However, if you’re a recovering collector of physical CD’s like me, a $10/month premium level subscription to Spotify is a must.

Spotify has been working hard to open up their platform to 3rd-party ISV’s and have made available a low-level C library (libspotify) as well as Javascript API’s that allow HTML5 applications embedded in Spotify’s native client application to interact with the platform. The result has been an explosion of really amazing social music applications.

In particular, the Soundrop application has really captured my attention since I started using it two months ago. Soundrop is an instance of an embedded HTML5 application as mentioned above that allows Spotify users to enter into collaborative listening ‘rooms’. In many respects this is similar conceptually to ‘rooms’ on turntable.fm. But there are some important differences.

Turntable.fm, all the rage a year or two ago, is still an awesome browser-based music application in my opinion. The basic idea of turntable is that you can enter into a ‘room’ and listen to a number of virtual DJ’s who take turns round-robin queuing tracks. Listeners and DJ’s can vote thumbs-up or down on the current track and depending on the policy set by the room’s creator, if enough people dislike the track it gets skipped. DJ’s get points for queuing tracks that are widely liked making it rather fun little game to DJ in a turntable.fm room.

Turntable.fm allows you to upload content from your local collection (so any MP3′s you have lying around) if you’re DJ’ing which is cool because there’s still many artists and tracks that are not available on Spotify. Hear something you like? Turntable.fm’s browser-based interface provides you with convenient links to iTunes, Amazon.com, last.fm and of course Spotify. This is really cool stuff and it’s a lot of fun but if you just want to passively listen (i.e. you’re not DJ’ing in a turntable.fm room) then the mix quality is hit-or-miss in my experience. Enter Soundrop on Spotify.

Soundrop, like turntable.fm, has ‘rooms’. There are 20-30 main rooms that are specific to different music genres (e.g. Classic Rock, Progressive Metal, Electronica…). Enter Soundrop, select a room, and you’re tuned into the stream with often hundreds of other music fans around the globe. Unlike turntable.fm however there are no DJ’s. Instead Soundrop is much more democratic allowing anyone to queue tracks available on Spotify, and vote on the tracks they like. The track with the highest vote tally in the queue shared by all room listeners gets played next.

This is really cool because you can drop into a Soundrop room, passively listen while you work, and occasionally focus the window to queue tracks, vote, or chat with other listeners. Integration with Spotify’s playlist facilities as well as deep integration with Facebook for sharing tracks and playlists makes the combination of Soundrop on Spotify a nearly perfect digital radio. But it gets cooler.

The other day I felt like listening to Reggae because it was sunny outside (one of the first really nice days in Puget Sound since last summer). What to listen to? Something new I think. I drop into the Reggae room in Soundrop and see that there about 200 people listening. What’s more the tracks at the top of the play queue have 7+ votes which is typically a good indication that the tracks are widely considered awesome by the room listeners. But I just want a couple of new tracks to check out and sync to my iPhone. Enter Soundrop ‘Save to playlist…’

One really great feature of Soundrop is the ability to capture the current play queue of any room to a Spotify playlist that you can later browse, preview, or raid for your own playlists offline. I’ve found hundreds of new artists and tracks this way in the two months I’ve been using Soundrop.

Recently I was in a bar and I didn’t like the music. This got me thinking and I came up with an idea: why not just connect a computer to the house PA, and create a Soundrop room for the entire bar? Then everyone with a smart phone can walk in, queue and vote, and enjoy the music. I hadn’t tried this out until last night while hanging out at my friend’s house.

My friend has his computer connected to his surround sound receiver (of course) and recently installed Spotify at my suggestion. We installed Soundrop inside of Spotify and then created a private room. I then pulled up the Soundrop application on my iPhone and because him and I are connected as friends on Facebook, his room got enumerated and displayed on my iPhone. I joined his room from my phone and we went back to eating pizza and talking about music.

“Oh I know… You’ve gotta hear this…” Couple swipes on my phone and it’s playing in his living room. That’s so cool! From now on, whenever I entertain the house will be rocking my Soundrop room effectively turning every smart phone in the house into a remote control.

Try it yourself and enjoy!

TopCoder Tutorials

A series of interesting tutorials from TopCoder that are educational and fun.

TopCoder Software Development Tutorials

Also, I’ve found these high-level Wikipedia articles to be useful review.

Wikipedia Algorithms Overview

Wikipedia Analysis of Algorithms

Wikipedia Big O Notation

Wikipedia Computational Complexity Theory

Wikipedia NP-complete

From the Wikipedia Big O notation page, this handy table:

 

Notation Name Example
O(1)\, constant Determining if a number is even or odd; using a constant-size lookup table or hash table
O(\log \log n)\, double logarithmic Finding an item using interpolation search in a sorted array of uniformly distributed values.
O(\log n)\, logarithmic Finding an item in a sorted array with a binary search or a balanced search tree as well as all operations in a Binomial heap.
O(n^c),\;0<c<1 fractional power Searching in a kd-tree
O(n)\, linear Finding an item in an unsorted list or a malformed tree (worst case) or in an unsorted array; Adding two n-bit integers by ripple carry.
O(n\log n)=O(\log n!)\, linearithmic, loglinear, or quasilinear Performing a Fast Fourier transform; heapsort, quicksort (best and average case), or merge sort
O(n^2)\, quadratic Multiplying two n-digit numbers by a simple algorithm; bubble sort (worst case or naive implementation), Shell sort, quicksort (worst case), selection sort or insertion sort
O(n^c),\;c>1 polynomial or algebraic Tree-adjoining grammar parsing; maximum matching for bipartite graphs
L_n[\alpha,c],\;0 < \alpha < 1=\,
e^{(c+o(1)) (\ln n)^\alpha (\ln \ln n)^{1-\alpha}}
L-notation or sub-exponential Factoring a number using the quadratic sieve or number field sieve
O(c^n),\;c>1 exponential Finding the (exact) solution to the travelling salesman problem using dynamic programming; determining if two logical statements are equivalent using brute-force search
O(n!)\, factorial Solving the traveling salesman problem via brute-force search; generating all unrestricted permutations of a poset; finding the determinant with expansion by minors.
Follow

Get every new post delivered to your Inbox.

Join 111 other followers