1

I'm having a small webpage with embedded soundcloud elements, and I would like to make a frequency spectrum analyzer thing. So far I've succeeded in making one that just uses a local sound file, but i can't figure out how to get audio data from the embedded elements.

Is there a way to extract sound data from the embedded elements?

If this is not a simple task, it would be equally satisfying to be able to analyze the sound just currently being played in the browser, if at all possible.

Thanks in advance : )

Code (Not really written by me, I found most of it from tutorials)

The HTML (embedded soundcloud tag)

<iframe id="em1" width="100%" height="450" scrolling="no" frameborder="no"     src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/144737157&amp;auto_play=false&amp;hide_related=false&amp;visual=true"></iframe>

The JS, where i wish to somehow attach the SoundCloudAudioSource to either the embedded tag or the entire browser window.

var SoundCloudAudioSource = function(audioElement) {
var player = document.getElementById(audioElement);
var self = this;
var analyser;
var audioCtx = new (window.AudioContext || window.webkitAudioContext); // this is because it's not been standardised accross browsers yet.
analyser = audioCtx.createAnalyser();
analyser.fftSize = 256; // see - there is that 'fft' thing. 
var source = audioCtx.createMediaElementSource(player); // this is where we hook up the <audio> element
source.connect(analyser);
analyser.connect(audioCtx.destination);
var sampleAudioStream = function() {
    // This closure is where the magic happens. Because it gets called with setInterval below, it continuously samples the audio data
    // and updates the streamData and volume properties. This the SoundCouldAudioSource function can be passed to a visualization routine and 
    // continue to give real-time data on the audio stream.
    analyser.getByteFrequencyData(self.streamData);
    // calculate an overall volume value
    var total = 0;
    for (var i = 0; i < 80; i++) { // get the volume from the first 80 bins, else it gets too loud with treble
        total += self.streamData[i];
    }
    self.volume = total;
};
setInterval(sampleAudioStream, 20); // 
// public properties and methods
this.volume = 0;
this.streamData = new Uint8Array(128); // This just means we will have 128 "bins" (always half the analyzer.fftsize value), each containing a number between 0 and 255. 
this.playStream = function(streamUrl) {
    // get the input stream from the audio element
    player.setAttribute('src', streamUrl);
    player.play();
}

};

user1291510
  • 265
  • 5
  • 14
  • share some code. do you use the widget or scoembed method? in general - the mp3 data is behind a url which is getting forwarded to amazon. – hwsw Apr 22 '14 at 15:15
  • Can i access this mp3 data from the embedded element? – user1291510 Apr 23 '14 at 11:19
  • i am not really familar with the sc embedded stuff, but you have this information already (https://api.soundcloud.com/tracks/144737157) - you can use their api to get the mp3 file. – hwsw Apr 23 '14 at 13:38
  • You should have a look at this answer: http://stackoverflow.com/questions/13455956/setup-web-audio-api-source-node-from-soundcloud – justGoscha Jun 23 '14 at 11:18

4 Answers4

1

Is there a way to extract sound data from the embedded elements?

No.

If this is not a simple task, it would be equally satisfying to be able to analyze the sound just currently being played in the browser, if at all possible.

This is also not possible.

idbehold
  • 16,833
  • 5
  • 47
  • 74
0

Thanks for the code.

One idea:

iframe src field has the relevant info to access to mp3 file:

src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/144737157&amp;auto_play=false&amp;hide_related=false&amp;visual=true"

tracks-id: 144737157

Using that information using their SDK:

SC.stream("/tracks/144737157",{autoLoad: true,  onload: function(){ this.play(); }});

or directly: You will be forwarded (302) to aws:

http://api.soundcloud.com/tracks/144737157/stream?client_id=201b55a1a16e7c0a122d112590b32e4a

hwsw
  • 2,596
  • 1
  • 15
  • 19
0
this.playStream = function(streamUrl) {
    // get the input stream from the audio element
    player.setAttribute('src', streamUrl);
    player.play();
}

The point is that you can not just pass/use the streamUrl directly into your own audioPlayer.

Because actually the stream URL is not the end point URL of the song you are expecting to play. The actual audio (in mp3 format) of the songs are being created 'on demand' when you send an http request to the stream url.

Afterwards you are being redirected to the endpoint URL of the song which is the physical path and you can play/analyze it by using this endpoint url you retrieved through sending the http request. The point is that, this endpoint URL of the audio has an expiration time which is sth. like 10-15 minutes.

To achieve what I am talking about here, you will have to do some tricks similar to this: (Not sure how you would do this in JavaScript but it will give you the idea)

public void Run()
        {
            if (!string.IsNullOrEmpty(TrackUrl))
            {
                HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(TrackUrl + ".json?client_id=YOUR_CLIENT_ID");
                request.Method = "HEAD";
                request.AllowReadStreamBuffering = true;
                request.AllowAutoRedirect = true;
                request.BeginGetResponse(new AsyncCallback(ReadWebRequestCallback), request);
            }
        }

        private void ReadWebRequestCallback(IAsyncResult callbackResult)
        {
            HttpWebRequest myRequest = (HttpWebRequest)callbackResult.AsyncState;
            HttpWebResponse myResponse = (HttpWebResponse)myRequest.EndGetResponse(callbackResult);


            using (StreamReader httpwebStreamReader = new StreamReader(myResponse.GetResponseStream()))
            {
                this.AudioStreamEndPointUrl = myResponse.ResponseUri.AbsoluteUri;
                this.SearchCompleted(this);
            }
            myResponse.Close();

        }

The AudioStreamEndPointUrl is the actual URL where your mp3 audio will reside for the next 15-20 mins. Note that each time you would like to stream a song, you will have to re-demand the endpoint URL.

Finally I suggest you not to spread your API key all over the internet; instead type like CLIENT_ID.

halil
  • 326
  • 1
  • 6
0

I think the link from JustGoscha points in the right direction. But this audio-visualization-with-web-audio-canvas-and-the-soundcloud-api link should satisfy your needs.

real.polka
  • 31
  • 3