Skip to content

How does the Freesound API works

Now that you know how to set up a basic script to work with the FreeSoundClient let's focus on how to take full advantage of the Freesound API.

NOTICE: The Freesound API is very well documented. Please don't forget that you can always rely on the Official Freesound API Documentation

INFO you can find the source code of the final version of this tutorial on GitHub


The search attributes

Querying the Freesound Database is the most important task of this library and understand how to build the right queries for your needs is in turn the most important thing to learn.

Let's review our first query:

from freesound import *

USER_ID = "<your-user-id>"
API_KEY = "<your-api-key>"

c = FreeSoundClient(USER_ID,API_KEY)
c.search(query="piano detuned")
Behind the scene search performs a GET request at the following url:
https://freesound.org/apiv2/search/text/?query=piano+detuned&fields=id%2Cname%2C&page_size=15&sort=score&normalized=0
There are many things specified in this url so let's break it down:
https://freesound.org/apiv2/search/text/
is the actual address that you want to reach, and it is the one that users use to perform text-based researches.

Starting from ? there is a list of url parameters that you pass to the request:

  • query=piano+detuned
  • fields=id%2Cname%2C
  • page_size=15
  • sort=score
  • normalized=0

The parameter query stores the text that you want to search in the database. You can use as many search keywords as you want. Just separate them with a space, and they will be automatically encoded with a + sign.

fields is the parameter which allows you to specify which information you want to retrieve from the database about a sound file. By default, the FreeSoundClient will always ask for the id and the name, but as you saw in the last tutorial, you can request other fields, such as download. There are many fields available for each sound instance, and you will see how to take advantage of this parameter in the next paragraphs.

page_size allows you to define how many results should be included in one request page (which is 15 by default). If you are planning to work with a higher number of sound files you should use a higher value for this parameter (max 150).

The parameter sort, by definition, will tell the database how the results should be sorted.

normalization is a feature that only applies when you include audio descriptors in your request. More about this in the next paragraphs.

One of the most important feature when performing a search request is the ability to filter out results that do not comply with your needs.

Let's make an example: for a specific project you need to collect only wav files with a 16bit resolution and sampled at 48000. To achieve this you can use another object provided by this library: the FreeSoundFilters, a utility class that helps you to format a list of filters for a valid request.

filters = FreeSoundFilters(type='wav',samplerate=44100,bitdepth=16)
c.search(query="piano detuned", filter=filters.aslist)
This call will produce the following output:

Output
Searching for piano detuned
https://freesound.org/apiv2/search/text/?query=piano+detuned&fields=id%2Cname%2C&page_size=15&sort=score&normalized=0&filter=type%3Awav+samplerate%3A44100+bitdepth%3A16
Found 256 results

With the same search keywords your query found 256 results instead of 469.

The resulting url changed, and it now includes the filter parameter:

filter=type%3Awav+samplerate%3A44100+bitdepth%3A16
Which decoded becomes:
filter=type:wav samplerate:44100 bitdepth:16
And this is exactly what the FreeSoundFilters does. Other than provide hints for valid filters,

filters hints
click to enlarge

this class and its method aslist, will format this list for you:

filters = FreeSoundFilters(type='wav',samplerate=44100,bitdepth=16)
print(filters.aslist)

Output
type:wav samplerate:44100 bitdepth:16

Sound files can also be filtered by one or multiple attributes, such as tag, and you might want to add a filter to get only sounds with specific tags. In such a scenario, instead of specifying a string as a value for tag, you can use a list like follows:

filters = FreeSoundFilters(type='wav',samplerate=44100,bitdepth=16, tag=['detuned','prepared'])
print(filters.aslist)
The list will be expanded as follows

Output
type:wav samplerate:44100 bitdepth:16 tag:detuned tag:prepared

a valid string for your query. With the additional tag filter your search result will contain 233 sounds

Output
Searching for piano detuned
https://freesound.org/apiv2/search/text/?query=piano+detuned&fields=id%2Cname%2Ctags&page_size=15&sort=score&normalized=0&filter=type%3Awav+samplerate%3A44100+bitdepth%3A16+tag%3Aprepared+tag%3Adetuned
Found 233 results

Filters allow ranges and conditional statementsCheck the dedicated section in the How To page

Getting analysis data

One of the most powerful feature of the Freesound API is the possibility to retrieve low level analysis data of each sound. There are two steps to achieve this: first you should add the analysis field to your fields parameter:

filters = FreeSoundFilters(type='wav',samplerate=44100,bitdepth=16,tag=['prepared','detuned'])
c.search(query="piano detuned", fields="analysis", filter=filters.aslist)
and then use the descriptors parameter to define which features should be retrieved from the server
filters = FreeSoundFilters(type='wav',samplerate=44100,bitdepth=16,tag=['prepared','detuned'])
desc = FreeSoundDescriptors([Descriptor.lowlevel_average_loudness,Descriptor.lowlevel_dissonance])
c.search(query="piano detuned", fields="analysis", filter=filters.aslist, descriptors=desc.aslist)
As for the filters, here you are using the FreeSoundDescriptors a utility class that from a list of Descriptor will help you to format a valid list of descriptors to query the database.

This request will be forwarded to the following url:

https://freesound.org/apiv2/search/text/?query=piano+detuned&fields=id%2Cname%2Canalysis&page_size=15&sort=score&normalized=0&filter=type%3Awav+samplerate%3A44100+bitdepth%3A16+tag%3Aprepared+tag%3Adetuned&descriptors=lowlevel.average_loudness%2Clowlevel.dissonance
which includes the descriptors parameter:
descriptors=lowlevel.average_loudness%2Clowlevel.dissonance
which decoded results in:
descriptors=lowlevel.average_loudness,lowlevel.dissonance
which is exactly what the FreeSoundDescriptors.aslist method does:
desc = FreeSoundDescriptors([Descriptor.lowlevel_average_loudness,Descriptor.lowlevel_dissonance])
print(desc.aslist)

Output
lowlevel.average_loudness,lowlevel.dissonance

The class Descriptor will provide you with hints to select a valid Freesound descriptor

filters hints
click to enlarge

Now print the full response of your search request. Add c.dump_results() at the end of your script:

c.dump_results()

Output
Found 233 results
--------------------
id:382539
name:Piano 59 A6.wav
analysis:
  average_loudness:0.0001156733164443101
  dissonance:
    min:0.41471666016070136
    max:0.49807483306121003
    dvar2:0.0003639381383530018
    dmean2:0.01738614605182347
    dmean:0.01092408269803247
    var:0.00020994146275491086
    dvar:0.0001980157397133761
    mean:0.48211296868812625
--------------------
id:382533
name:Piano 46 A5.wav
analysis:
  average_loudness:2.3593042398314997e-07
  dissonance:
    min:0.0
    max:0.4992182563553003
    dvar2:0.0072741507223403855
    dmean2:0.09399208175807922
    dmean:0.0588165176322519
    var:0.005893807680049213
    dvar:0.003078075759614881
    mean:0.38633684975614424
--------------------
id:382510
name:Piano 20 G4.wav
analysis:
  average_loudness:0.00035443490551525787
  dissonance:
    min:0.09704220532826434
    max:0.4688467280334164
    dvar2:0.004038197436062609
    dmean2:0.06455182028183501
    dmean:0.03937605841764635
    var:0.007301079374823115
    dvar:0.001507330795200205
    mean:0.2609139747182671
--------------------
12 RESULTS OMITTED
--------------------
timestamp:2024-03-01T17:49:18.541707

count:233

While the resulting avarage_loudness of each file is one value the dissonance is presented as a dict of values containing statics of the dissonance which is performed frame by frame.

NOTICE: The official Freesound Analysis Documentation states: the analysis sample rate is 44100Hz and the audio file’s channels are mixed down to mono. For the lowlevel namespace the frame size is 2048 samples with a hop size of 1024, while for the tonal namespace the frame size is 4096 and the hop size 2048.

Requesting multiple fields

If you know want to download the resulting sound, but you still want to get the analysis data of your sounds, you know that you should add the download keyword to the fields search parameter. The url parameter fields that you encoded in your last query is:

fields=id%2Cname%2Canalysis
which decoded is:
fields=id,name,analysis
a coma-separated string of values. Since id and name are always included in the fields of each FreeSoundClient.search() request, you just needed to add the analysis field to retrieve the low level descriptors from the database. To add the download field and retrieve the sound file download url from the server, you can reformulate the search request as follows:
filters = FreeSoundFilters(type='wav',samplerate=44100,bitdepth=16, tag=['prepared','detuned'])
desc = FreeSoundDescriptors([Descriptor.lowlevel_average_loudness,Descriptor.lowlevel_dissonance])
fields = FreeSoundFields([Field.analysis, Field.download])
c.search(query="piano detuned", fields=fields.aslist, filter=filters.aslist, descriptors=desc.aslist)
As for the descriptors the FreeSoundFields utility class will assist you to formulate a valid coma-separated string of fields to be included in your search result.
fields = FreeSoundFields([Field.analysis, Field.download])
print(fields.aslist)
will result in

Output
analysis,download

which are the fields that will be appended to id,name. Like the class Descriptor, Field will provide you with hints to choose valid fields for you requests

filters hints
click to enlarge

If you find yourself in the need of retrieve as much information as possible from a search query, Field has a special method called all(), which, by definition, will allow you to query all the fields of a sound in one search result.

c.search(query="piano detuned", fields=Field.all(), filter=filters.aslist, descriptors=desc.aslist)

Output
Found 233 results
--------------------
id:382539
url:https://freesound.org/people/lomographicmusic/sounds/382539/
name:Piano 59 A6.wav
tags:['piano', 'detuned', 'prepared']
description:Simple detuned piano sound recorded with Tascam DP008. 

Son de piano détuné capté au fantastique Tascam DP008.
geotag:None
created:2017-03-01T00:35:20
license:https://creativecommons.org/licenses/by/4.0/
type:wav
channels:2
filesize:321032
bitrate:0
bitdepth:16
duration:1.81966
samplerate:44100.0
username:lomographicmusic
pack:https://freesound.org/apiv2/packs/21508/
download:https://freesound.org/apiv2/sounds/382539/download/
previews:
images:
num_downloads:43
avg_rating:0.0
num_ratings:0
rate:https://freesound.org/apiv2/sounds/382539/rate/
comments:https://freesound.org/apiv2/sounds/382539/comments/
num_comments:0
comment:https://freesound.org/apiv2/sounds/382539/comment/
similar_sounds:https://freesound.org/apiv2/sounds/382539/similar/
analysis:
  average_loudness:0.0001156733164443101
  dissonance:
    min:0.41471666016070136
    max:0.49807483306121003
    dvar2:0.0003639381383530018
    dmean2:0.01738614605182347
    dmean:0.01092408269803247
    var:0.00020994146275491086
    dvar:0.0001980157397133761
    mean:0.48211296868812625
analysis_frames:https://freesound.org/data/analysis/382/382539-fs-essentia-extractor_legacy_frames.json
analysis_stats:https://freesound.org/apiv2/sounds/382539/analysis/
ac_analysis:
--------------------
14 RESULTS OMITTED
--------------------
timestamp:2024-03-01T17:52:42.207937

count:233

Saving the analysis data

You already know how to download audio files from the Freesound Database, but the FreeSoundClient allows you to store also the analysis results of your searches thanks to the method FreeSoundClient.write_results_list. Calling

c.write_results_list()
The program will prompt to choose an output folder. Pressing the return key will create a file called results_list.json prefixed with a timestamp in the same folder as your script. Feel free to specify another folder either using an absolute or a relative path, and a filename (a time stamp will always be included).

Other possible methodologies

All the utility classes presented in this tutorial have been developed to provide a user-friendly interface and help the users to focus on their goal without the need of visiting the official Documentation to formulate valid queries. But the search method does actually work without them. Nothing prevents the user to formulate this request using strings. Your last call to search:

filters = FreeSoundFilters(type='wav',samplerate=44100,bitdepth=16,tag=['prepared','detuned'])
desc = FreeSoundDescriptors([Descriptor.lowlevel_average_loudness,Descriptor.lowlevel_dissonance])
fields = FreeSoundFields([Field.analysis, Field.download])
c.search(query="piano detuned", fields=fields.aslist, filter=filters.aslist, descriptors=desc.aslist)
can be in fact reformulated as follows:
c.search(query="piano detuned", fields="analysis,download", filter="type:wav samplerate:44100 bitdepth:16 tag:prepared tag:detuned", descriptors="lowlevel.average_loudness,lowlevel.dissonance")
or even combining the 2 methodologies.

Conclusion

You should now know have a good overview of all the basic features of the freesound-client library. In the Appendix section of this Documentation you can find the lists of all the valid parameters that can be used in search queries. Remember that the official Freesound API Documentation should be the most important resource to dive deeper in what the Freesound Database has to offer.

Feel free to visit the How To page for a more problem oriented guide and for more advanced topic on how to use the freesound-client library.