Kofi / Illestpreacha
Code is Poetry & Data is Poetry

Follow

Code is Poetry & Data is Poetry

Follow
DecibelsChallenge_GlobalJukeBox

DecibelsChallenge_GlobalJukeBox

Sonification of Instruments by Cultural Find

Kofi / Illestpreacha's photo
Kofi / Illestpreacha
·Jan 15, 2023·

8 min read

For the first Decibels Challenge, the dataset provided was from https://theglobaljukebox.org/, in particular the following CSV:

https://github.com/theglobaljukebox/instruments/blob/main/raw/data.csv

IllestPreacha · Decibels - GlobalJukeBox - CulturalRepresentations

Sonification Steps

  • Started by checking what the data had in store, especially concerning what cultures were heavily represented by the data

  • Did this by cleaning the data in Python that can be seen in the first portion of code

  • Followed by the sonification in SonicPi

Python Code

#reading the csv file

import pandas as pd
df = pd.read_csv("SonificationChallenge/InstrumentData.csv")
print(df)

# Output
'''
Instrument_# I-id Instrument_Name Archival_Culture_Name Sachs_Number 
0 52 1622 DRUM A CHINA 211
1 36 1623 CONDUCTOR A CHINA 600000000
2 32 1606 IDIOPHONE A CHINA 112212
3 29 1597 BELL A CHINA 111242121
4 28 1600 LITHOPHONE A CHINA 111221
... ... ... ... ... ...
1775 31 1243 RATTLE ZUNI 11213
1776 53 1249 DRUM ZUNI 1112
1777 45 1242 DRUM ZUNI 21125
1778 29 1248 BELLS ZUNI 11124212
1779 31 1239 RATTLE ZUNI 11213

Sachs_Suffix V1 V2 V3 V4 ... V6 V7 V8 V9 V10 V11 V12 V13 
0 2 0 0 0 2 ... 6 0 8 9 0 0 0 0
1 0 0 0 0 3 ... 5 4 1 10 14 0 0 0
2 3 0 0 7 3 ... 7 2 4 1 0 1 0 1
3 3 0 0 4 3 ... 8 1 1 0 0 0 1 1
4 3 6 0 6 3 ... 7 2 1 4 0 0 1 1
... ... .. .. .. .. ... .. .. .. .. ... ... ... ...
1775 3 0 0 2 2 ... 1 3 1 12 10 9 1 6
1776 3 0 3 3 4 ... 1 2 10 12 0 0 5 15
1777 11 0 5 4 2 ... 1 2 10 1 0 0 6 15
1778 0 2 0 2 2 ... 1 2 10 12 0 0 2 2
1779 3 0 0 1 2 ... 1 3 10 1 3 0 1 14

V14 Active
0 0 1
1 0 1
2 0 1
3 0 1
4 0 1
... ... ...
1775 6 1
1776 6 1
1777 6 1
1778 9 1
1779 9 1

[1780 rows x 21 columns]
'''
#getting information on the type of columns that are within the Dataframe
df.info()

#output

'''
<class 'pandas.core.frame.DataFrame'> RangeIndex: 1780 entries, 0 to 1779 Data columns (total 21 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Instrument_# 1780 non-null int64 1 I-id 1780 non-null int64 2 Instrument_Name 1780 non-null object 3 Archival_Culture_Name 1780 non-null object 4 Sachs_Number 1780 non-null object 5 Sachs_Suffix 1780 non-null int64 6 V1 1780 non-null int64 7 V2 1780 non-null int64 8 V3 1780 non-null int64 9 V4 1780 non-null int64 10 V5 1780 non-null int64 11 V6 1780 non-null int64 12 V7 1780 non-null int64 13 V8 1780 non-null int64 14 V9 1780 non-null int64 15 V10 1780 non-null int64 16 V11 1780 non-null int64 17 V12 1780 non-null int64 18 V13 1780 non-null int64 19 V14 1780 non-null int64 20 Active 1780 non-null int64 dtypes: int64(18), object(3) memory usage: 292.2+ KB

'''
#getting information from the csv
df.describe()
Instrument_#I-idSachs_SuffixV1V2V3V4V5V6V7V8V9V10V11V12V13V14Active
count1780.0000001780.0000001780.0000001780.0000001780.0000001780.0000001780.0000001780.0000001780.0000001780.0000001780.0000001780.0000001780.0000001780.0000001780.0000001780.0000001780.0000001780.0
mean24.877528895.8606749.1629213.9983150.6202253.1342702.5505621.6960671.9174162.0494388.0938207.0382024.1095510.4640452.7764046.3022473.8089891.0
std12.327946517.91531113.1801794.5093741.6366502.5275221.8031960.9372001.7593981.1806125.5724235.9972545.9460591.7686133.0426064.8204053.5759690.0
min5.0000001.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000001.0
25%15.000000446.7500000.0000000.0000000.0000001.0000002.0000001.0000001.0000001.0000001.0000000.0000000.0000000.0000000.0000002.0000001.0000001.0
50%25.000000896.5000003.0000000.0000000.0000003.0000002.0000002.0000001.0000002.00000010.00000010.0000000.0000000.0000001.0000006.0000002.0000001.0
75%31.0000001346.25000017.0000009.0000000.0000005.0000003.0000002.0000002.0000003.00000013.00000011.00000010.0000000.0000006.0000006.0000005.0000001.0
max53.0000001791.00000092.00000011.0000009.0000009.00000010.0000004.0000008.0000004.00000016.00000016.00000016.0000009.0000009.00000017.00000015.0000001.0
#finding the unique values in Archival_Culture_Name

df.Archival_Culture_Name.unique()

'''
array(['A CHINA', 'ABELAM', 'AINU', 'AMHARA', 'ANCIENTGREECE', 'ANDALUCIA', 'ANDAMAN', 'ARAUCANIANS', 'ASHANTI', 'BAHIMA', 'BALI', 'BARA', 'BASQUE', 'BAULE', 'BEDOUIN', 'BEMBA', 'BETSILEO', 'BONTOK', 'BRI URB BAR', 'BUKA', 'BULGARIA', 'C RUSSIA', 'CAMAYURA', 'CARIBOUESK', 'CARRIACOU', 'CASTILE', 'CAYAPA', 'CHAGGA', 'CHEREMIS', 'CHEYENNE', 'CHOPI', 'CHUKCHEE', 'CREE', 'CUNA', 'DINKA', 'DOGON', 'DUSUN', 'EGYPT', 'EGYPTANCIENT', 'EKONDA', 'FIJI', 'FLATHEAD', 'FR URB BAR', 'GALICIA', 'GEORGIA', 'GER URB BAR', 'GILYAK', 'GOAJIRO', 'GOND', 'HAITI', 'HANUNOO', 'HAUSA', 'HAWAII', 'HEBREW', 'HUNGARY', 'HUPA', 'IBAN', 'IRISH', 'IROQUOIS', 'IT URB BAR', 'IWALIPETI', 'JAPAN', 'JAVA', 'JIVARO', 'KAZAK', 'KERALA', 'KOREA', 'KRAHO CANELA', 'KUNG', 'KUTENAI', 'LALA', 'LAOS', 'LAPPS', 'M GREECE', 'MALEKULA', 'MANUS', 'MAORI', 'MARING', 'MARQUESAS', 'MBUTI', 'MNONG GAR', 'MORAVIA', 'MOROCCO GEN', 'MOSQUITO', 'MOTILON', 'MURRAYTORRES', 'N AUSTRALIA', 'N INDIA', 'N RUMANIA', 'N RUSSIA', 'N.CAYAPO', 'NORTH ITALY', 'NORWAY', 'NUER', 'OMAHA', 'PAPAGO', 'PERSIA', 'PERU ANCIENT', 'POMO', 'PONDO', 'PUERTO RICO', 'PWO KARENS', 'QUECHUA', 'RIF', 'RUANDA', 'S INDIA', 'S RUMANIA', 'S US', 'SAMOA', 'SAMOYEDE', 'SANTODOMINGO', 'SEMANG', 'SHILLUK', 'SHLUH', 'SLOVAKIA', 'SOFIA DIST', 'SOLOMON', 'SOTHO', 'SOUTHERN USA', 'SWAZI', 'TANALA', 'TARAHUMARA', 'TETON DAKOTA', 'THONGA', 'TIBET', 'TIKOPIA', 'TODA', 'TOMA', 'TOPOKE', 'TORRES', 'TRASOSMONT', 'TRUK', 'TSIMSHIAN', 'TUAREGHOG', 'TUCUNA', 'TURKEY', 'TURKMAN', 'US URB BAND', 'US URB SYM', 'UTE', 'VIETNAM', 'WASHO', 'WEST FRANCE', 'WOLOF', 'XHOSA', 'YAGUA', 'YAKUT', 'YAQUI', 'YARURO', 'YORUBA', 'ZULU', 'ZUNI'], dtype=object)
'''
#Make a DF that has the value counts of the cultures

Cultures = df["Archival_Culture_Name"].value_counts()
print(Cultures)

'''
JAVA 65 JAPAN 50 VIETNAM 36 KOREA 33 SOUTHERN USA 29 .. WASHO 2 LAPPS 2 YAKUT 2 YARURO 1 ANDAMAN 1 Name: Archival_Culture_Name, Length: 152, dtype: int64
'''
#changing column names
Cultures.columns = ["Archival_Culture_Name","Count"]
#rechecking how the new information is statistically broken down
Cultures.describe()

'''
count 152.000000 
mean 11.710526 
std 8.932144 
min 1.000000 
25% 5.000000 
50% 10.000000 
75% 15.000000 
max 65.000000 
Name: Archival_Culture_Name, dtype: float64
'''
#Turn Cultures DF into the CSV
from pathlib import Path  
filepath = Path("SonificationChallenge/InstrumentData_CultureCount.csv")  
filepath.parent.mkdir(parents=True, exist_ok=True)  
Cultures.to_csv(filepath)

SonicPi Code

require 'csv'

#This Code has extra sound Effects for the lower ended sounds
#The Other Audio will not have this

#naming the Dataset DipInCode and going to read the file
#Sorting the CSV to have variance by reverse Alphabetical Order
#turning  the csv into an array


=begin

Stats that I Will use to make this sonification

count    152.000000
mean      11.710526
std        8.932144
min        1.000000
25%        5.000000
50%       10.000000
75%       15.000000
max       65.000000

=end
Culture = CSV.parse(File.read("C:/Users/skyis/SonificationChallenge/InstrumentData_CultureCount.csv"), headers: true)

#Will make a shuffle of all 152 Cultures present to add variance to the sounds
#also making "different" arrangements in terms of temporal awareness
# .to_f is needed to change string to float

counter = (0..151).to_a.shuffle() #length of data set


i = 0


live_loop :cultural do

  #this will refer to the cultures seperated in the quadrants
# the note played by the sound represents the amount of instruments played

  if Culture[counter[i]]["Archival_Culture_Name"].to_f >= 15
    use_synth :piano
    play Culture[counter[i]]["Archival_Culture_Name"].to_f
    puts Culture[counter[i]]["Archival_Culture_Name"]
    #loop thru
    #need to.f as it is to float
  end

  if Culture[counter[i]]["Archival_Culture_Name"].to_f <= 5
    use_synth :chipbass
    #sample :ambi_choir
    play Culture[counter[i]]["Archival_Culture_Name"].to_f
    puts Culture[counter[i]]["Archival_Culture_Name"]
    #loop thru
    #need to.f as it is to float
  end

  if Culture[counter[i]]["Archival_Culture_Name"].to_f <= 10 and Culture[counter[i]]["Archival_Culture_Name"].to_f > 5
    use_synth :prophet
    #sample :ambi_choir
    play Culture[counter[i]]["Archival_Culture_Name"].to_f
    puts Culture[counter[i]]["Archival_Culture_Name"]

  end

  if Culture[counter[i]]["Archival_Culture_Name"].to_f > 10 and Culture[counter[i]]["Archival_Culture_Name"].to_f <= 15
    use_synth :pretty_bell
    sample :perc_snap
    play Culture[counter[i]]["Archival_Culture_Name"].to_f
  end

  i += 1

  if i < 151
    i += 1
  end

  if i >= 151
    i == 0
  end
  sleep [0.5,1].choose
end

Second SonicPi Code - With Synth Options

require 'csv'

#This Code has extra sound Effects for the lower ended sounds

#naming the Dataset DipInCode and going to read the file
#Sorting the CSV to have variance by reverse Alphabetical Order
#turning  the csv into an array


=begin

Stats that I Will use to make this sonification

count    152.000000
mean      11.710526
std        8.932144
min        1.000000
25%        5.000000
50%       10.000000
75%       15.000000
max       65.000000

=end
Culture = CSV.parse(File.read("C:/Users/skyis/SonificationChallenge/InstrumentData_CultureCount.csv"), headers: true)

#Will make a shuffle of all 152 Cultures present to add variance to the sounds
#also making "different" arrangements in terms of temporal awareness
# .to_f is needed to change string to float

counter = (0..151).to_a.shuffle() #length of data set


i = 0


live_loop :cultural do

  #this will refer to the cultures seperated in the quadrants
  # the note played by the sound represents the amount of instruments played

  if Culture[counter[i]]["Archival_Culture_Name"].to_f >= 15
    use_synth [:pretty_bell,:piano,:chipbass].choose
    play Culture[counter[i]]["Archival_Culture_Name"].to_f
    puts Culture[counter[i]]["Archival_Culture_Name"]
    #loop thru
    #need to.f as it is to float
  end

  if Culture[counter[i]]["Archival_Culture_Name"].to_f <= 5
    use_synth [:pretty_bell,:piano,:chipbass].choose
    #sample :ambi_choir
    play Culture[counter[i]]["Archival_Culture_Name"].to_f
    puts Culture[counter[i]]["Archival_Culture_Name"]
    #loop thru
    #need to.f as it is to float
  end

  if Culture[counter[i]]["Archival_Culture_Name"].to_f <= 10 and Culture[counter[i]]["Archival_Culture_Name"].to_f > 5
    use_synth [:pretty_bell,:piano,:chipbass].choose
    #sample :ambi_choir
    play Culture[counter[i]]["Archival_Culture_Name"].to_f
    puts Culture[counter[i]]["Archival_Culture_Name"]

  end

  if Culture[counter[i]]["Archival_Culture_Name"].to_f > 10 and Culture[counter[i]]["Archival_Culture_Name"].to_f <= 15
    use_synth [:pretty_bell,:piano,:chipbass].choose
    play Culture[counter[i]]["Archival_Culture_Name"].to_f
  end

  i += 1

  if i < 151
    i += 1
  end

  if i >= 151
    i == 0
  end
  sleep [0.5,1].choose
end
 
Share this