What's new? | Help | Directory | Sign in
Google
cl-en
Echonest API support in Lisp
  
  
  
  
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
== Welcome

This is a Common Lisp library, cl-en, for accessing the echonest <http://the.echonest.com/> developer API. It is current as of mid April 2008. At that time there were only two API calls.

== Copyright & Default License

The copyright on CL-EN is held by Ben Hyde <bhyde@pobox.com>, who grant you a license
under Apache License, Version 2.0; you may not use this work except in compliance with
the license. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied. See the License for the specific language governing
permissions and limitations under the License.

This work depends upon other works and it is certain that their licenses vary.

== Library's Dictionary

* en:enqueue-for-analysis <filename/pathname> -> <response-object>

Sends, via HTTP, the mp3 file denoted to Echonest for analysis. The response object describes their response. Errors, at the TCP/HTTP level, maybe raised. Their response may contain errors. A job identifier is returned in the response object and is used to poll for job status or results. You will need to persist that id until you have retieved the job results.

- en:poll-for-analysis <identifier> -> <analysis>|<response>

Polls the Echonest service for a previously requsted analysis. The job's identifier is that returned when the analysis was originally requested.

- en:*key*

A string containing your Echonest API key. This is loaded when the library is loaded, and read from the file key.text which you will need to edit.

- en:*count*

A fixnum incremented on each API request. Note that your API account is limited to some number of requests per day.

We traffic in objects of these kinds.

- en:analysis, an object
- en:track, an object
- en:segment, an object
- en:section, an object
- en:request, an object

For insight into these data structures
- See the file data-model.lisp,
- the Relax NG declaration of the XML found in the rng subdirectory, and
- browse an en:analysis object using your inspector.

== Installation

The library is available from google code. Down load directly from the code repository there.

svn checkout https://cl-en.googlecode.com/svn/trunk/ cl-en

The library includes an ASFD description.

The library has direct dependencies on CXML-RNG, and CL-PPCRE, and indirect dependencies on many other things.

== Implementation

The XML responses are run thru progressively thru CXML, CXML-RNG, and en::*the-sax-handler*, an instance of en::sax-handler. The relax ng schema defined in rng/analysis.rng is used to validate, via cxml-rng:parse-compact, so the methods of en::sax-handler needn't be particularly paranoid. Those methods assemble the objects and are guided by simple tables build by the macros seen in data-model.

I noticed as building this a few random things about the echonext api implementation. The unusual http error code 597 is returned in some scenarios for malformed requests, such as unknown method. They don't appear to support HTTP chunking. The upload method has parameters in both the URL and in the POST body.

The xml to object mapping could be more elegant.

I am not using this library, writting it was a lark. Just ask and I'll grant you permission to commit changes.

== Example

In the following example the "..." are places where some text has been
removed. So you can repeat this example the mp3 was pulled from PodSafeAudio.com (e.g. here[1]) which grants a generous license.

[1] <http://podsafeaudio.com/jamroom/bands/1310/Live_from_the_Loft.php>

EN> *key*
"put-api-key-here"
EN> (setf *key* "g...f")
"gjsrfa682c24j5ubqcyvze6f"
EN> (en:enqueue-for-analysis "/Users/.../Give it all Away.mp3")
#<RESPONSE {118E7369}>
EN> (describe *)
#<RESPONSE {118E7369}> is an instance of class #<STANDARD-CLASS RESPONSE>.
The following slots have :INSTANCE allocation:
PARENT NIL
ID "7afff36c06ac0527a05b8bbf38061458"
INPUT "Give it all Away.mp3"
STATUS "analyzing"
; No value
EN> (en:poll-for-analysis "7afff36c06ac0527a05b8bbf38061458")
#<ANALYSIS {117693C9}>
EN> (describe *)
#<ANALYSIS {117693C9}> is an instance of class #<STANDARD-CLASS ANALYSIS>.
The following slots have :INSTANCE allocation:
PARENT NIL
DECODER #<DECODER {11DA11D9}>
TRACK #<TRACK {11730661}>
; No value
EN> (describe (slot-value ** 'en:track))
#<TRACK {11730661}> is an instance of class #<STANDARD-CLASS TRACK>.
The following slots have :INSTANCE allocation:
PARENT #<ANALYSIS {117693C9}>
VERSION "22"
USABLE-DURATION 158.13087
DURATION 160.86063
TAGS ((LOUDNESS-DYNAMICS-VARIANCE . 11.04)
(TIMBRE-MEAN 39.373 0.788 52.76 0.443 -88.076 11.548
-25.49 -5.654 9.169 -1.786 -2.919 -9.08)
(END-OF-FADE-IN . 2.60063)
(LOUDNESS-BEGIN-VARIANCE . 32.315)
(LOUDNESS-BEGIN-MEAN . -23.489)
(BEAT-VARIANCE . 0.016)
(TIME-SIGNATURE-STABILITY . 0.882)
(LOUDNESS-DYNAMICS-MEAN . 5.965)
(TIMBRE-VARIANCE 22.109 3224.902 840.106 892.311
833.097 587.454 518.639 293.838 460.695 173.574
174.673 355.605)
(LOUDNESS-MAX-VARIANCE . 18.736)
(LOUDNESS-MAX-MEAN . -17.523)
(SEGMENT-DURATION-VARIANCE . 0.03111)
(SIZE-TIMBRE . 12)
(PITCH-MEAN 0.472 0.478 0.475 0.666 0.662 0.245 0.277
0.358 0.506 0.401 0.305 0.399)
(START-OF-FADE-OUT . 160.86063) (TATUM . 0.24578)
(TIME-LOUDNESS-MAX-MEAN . 0.08579)
(NUMBER-OF-TATUMS . 658) (TEMPO-CONFIDENCE . 0.622)
(LOUDNESS . -11.682) (TEMPO . 61.139)
(SEGMENT-DURATION-MEAN . 0.30523)
(NUMBER-OF-SECTIONS . 15) (TATUM-CONFIDENCE . 0.851)
(TIME-SIGNATURE . 4) (NUMBER-OF-BEATS . 220)
(SIZE-PITCHES . 12)
(PITCH-VARIANCE 0.077 0.066 0.088 0.068 0.09 0.023
0.037 0.058 0.086 0.066 0.04 0.05)
(NUMBER-OF-SEGMENTS . 527)
(NUMBER-OF-TATUMS-PER-BEAT . 4))
TATUMS #(0.0 0.17974 0.42207 0.66466 0.90906 1.15321 1.39675
1.64019 1.88414 2.1286 2.37392 2.62036 2.86645
3.11305 3.36113 3.6101 3.85969 4.10902 4.35746
4.60503 4.85198 5.09769 5.34427 5.59086 5.83744
6.08402 6.33061 6.57719 6.82377 7.06984 7.31591
...
158.3059 158.55118 158.79732 159.04443 159.29042
159.53613 159.77977 160.0207 160.22772 160.39294
160.56094 160.7315)
SECTIONS (#<SECTION {1268B709}> #<SECTION {118540A9}>
#<SECTION {118540B9}> #<SECTION {118540C9}>
#<SECTION {118540D9}> #<SECTION {118540E9}>
#<SECTION {118540F9}> #<SECTION {11854109}>
#<SECTION {11854119}> #<SECTION {11854129}>
#<SECTION {11854139}> #<SECTION {12E0D001}>
#<SECTION {12E0D011}> #<SECTION {12E0D021}>
#<SECTION {12E0D031}>)
SEGMENTS (#<SEGMENT {11713A69}> #<SEGMENT {11713A79}>
#<SEGMENT {11713A89}> #<SEGMENT {11713A99}>
#<SEGMENT {11713AA9}> #<SEGMENT {11713AB9}>
...
#<SEGMENT {12E0D501}> #<SEGMENT {12E0D511}>
#<SEGMENT {12698F49}>)
; No value
EN>

There were 527 elements in the track's segments and 658 elements in it's tatums.
Show details Hide details

Change log

r5 by bh...@pobox.com on Apr 11, 2008   Diff
Record provinance of the mp3 used for the
example.
Go to: 
Project members, sign in to write a code review

Older revisions

r4 by bh...@pobox.com on Apr 11, 2008   Diff
Typo
r2 by bh...@pobox.com on Apr 11, 2008   Diff
Initial checkin
All revisions of this file

File info

Size: 7985 bytes, 165 lines