It’s been a month long spare time hackathon, but so stoked to release this Pokemon Card Recognizer for the Meta game streaming community using some awesome Computer Vision, Deep Learning, and Robotics tech!
This will help annotation of booster pack opening videos and other such Metaverse gaming experiences. It’s benchmarked quite accurately thus far! I’m so excited to support the dream of professional gaming. Are professional gaming careers actually actualizable by a large percentage of the population in the near future?
By popular demand, I was asked to investigate the origin of the vocal riff in the first 10 seconds of Light’s “Prodigal Daughter” track on the PEP Album.
What is the vocal riff in the first 10 seconds?
At the VIP Q/A at the San Francisco Regency Ballroom concert on 4/6/2022, Lights revealed some details on the vocal riff in Prodigal Daughter.
According to Lights, the vocal riff comes from royalty-free samples that are bundled as part of Apple’s Logic Pro, a popular music production software studio. The vocal riff loop is modified with Logic Pro effects such as Flex Time to create the final sound.
I decided to look into this with my own Logic Pro installation (Logic Pro 10.7.3, macOS Monterey 12.3.1, Macbook Pro 16-in 2021). Upon further investigation, it turns out…
Light’s statement is ACCURATE!
The vocal riff used in Prodigal daughter can indeed be found within the Jam Pack WorldMusic Apple Loops that are installable via the Sound Library Manager as additional downloadable free content.
According to Apple, these samples “may be used on a royalty-free basis to create your own original soundtracks for your film, video and audio projects” (https://support.apple.com/en-gb/HT202939), which is why the Prodigal Daughter production can use use them legally.
The opening vocal riff in Prodigal Daughter is actually not one but likely two free samples stitched together. The closest matches to Prodigal Daughter are the temporal merging of the “Bollywood Lyric 02” and “Bollywood Lyric 08” samples. Here is the raw audio for these samples:
Some other close candidates are “Bollywood Lyric 01” and “Bollywood Lyric 10,” although the vocal pitch and intonation sound too different for these to be the correct hits:
So the raw audio does in fact exist in Logic Pro! Where did these loops come from before they were bundled with Logic Pro?
There are a total of 23 such Bollywood loops (named “Bollywood Lyric 01” – “Bollywood Lyric 23”) in the Apple Jam Pack. The male singer sounds the same in each of the loops, so it is probably the same vocalist in all the tracks. It could be the case that the loops come from one or multiple songs of the original male vocalist’s discography.
To attempt to identify the singer via audio fingerprinting, each of the loops was run through Shazam as well as Google Music’s recognition service for the longer (>2 sec of non-silent audio) loops. In many cases, a recognition result could not be obtained. The results for loops that did process are listed below:
In all cases, the audio snippet had verified usage in some part of the piece, so the recognition results are accurate (and consistently reproducible). However, the results from Shazam and Google Music are heavily biased to recent musical releases in the last 10 years where DJs, EDM musicians, etc are just re-mixing the pre-existing Apple loops. This does not tell us much about the original vocal riff, which was likely created much earlier.
These Bollywood loops are surprisingly popular and widely used! The earliest timestamps of release of the recognized tracks date back to 2010, indicating that the loops have been in Logic Pro for some time. The results from the music recognition services trace the vocal riff back to a widely-released “Bollywood Vocal Ringtone” under the artist name “The Ringtones” that existed in 2010, probably made for flip phones:
This release exists both on YouTube and Spotify under several “albums” which are actually collections of short ~10-30 second mobile ringtones. Each of these collections was released by the artist named “The Ringtones” in timespans ranging from 2010, 2011, and 2012. Here are some of the collection hits on Spotify:
The metadata for the ringtone (which appears to be credible since it exists both on YouTube and Spotify) is:
Provided to YouTube by Kontor New Media Bollywood Vocal Ringtone — Sound Effects Ringtones Greatest Hits ℗ Music4license Released on: 2010-01-18 Artist: Sound Effects Ensemble Composer: Bel Air Music Publisher: Edition Incontro Musikverlag
So the vocal riff used in Prodigal Daughter was previously a freely-distributed Apple loop. This loop came from a mobile ringtone, distributed as far back as 2010 on Spotify and possibly earlier on Pandora, Burnlounge, possibly Napster, and others. Where did this mobile ringtone come from?
Some additional 2012 releases of the Ringtone collection indicate a UPC number which might allow further tracing of the publisher of the ringtone collections in hopes of figuring out where the ringtone was ripped from:
The UPC number search unfortunately did not yield more information. Unfortunately, this about as far as I was able to trace the digital history of the loop.
Having reached a technological dead end with AI, I tried the human crowd-sourcing approach — posting on WhatsApp to a community of 200+ mostly age 60+ Indian relatives and family friends in hopes of receiving a clue. Unfortunately, this did not yield any conclusive results either. The mystery remains unsolved. We may have to crowd-source further.
Based on TCGPlayer.com API, here is the distribution of individual card resale prices for Evolving Skies and Fusion Strike sets:
Based on this and the empirical pulls from booster packs, the $ value of each booster pack in a booster box can be calculated:
Individually Pokemon booster packs sell for $3-4, but the median actual worth of cards in the booster packs is $1-2. However, if you pull a rare card such an alternate art, the actual value of the booster pack could be as much as ~$50. So pulling just one booster pack with a good alternate art can easily recover half the cost of a booster box of 36 booster packs (~$90-100).
In my case, I found the actual value of my Evolving Skies booster box based on empirical pulls was ~$110 whereas Fusion Strike booster box was $51. This indicates that, of the current sets, Evolving Skies can be a great investment, if on sale.
SBatch (SLURM code) can be annoying to write and, due to popular demand, I have decided to release some utility scripts I use to auto-generate SLURM. EXC and EXCB are convenience python scripts that allow people to specify jobs and job arrays in simple call files that are then turned into SLURM code and run on the cluster.
EXC: You specify a number of CPUs and the command you want run and an sbatch script is automatically generated with the job (from template) and executed.
#!/usr/bin/python
import os
import sys
#input checking
if(len(sys.argv)!=3):
print "USAGE: python exc.py [NUM_CPU] [COMMAND]"
sys.exit()
numCPU = int(sys.argv[1])
if(numCPU > 24):
print "ERROR: Only 24 CPUs on a node."
sys.exit()
cmd = sys.argv[2]
#params
account = 'xxxx'
username = 'xxxx'
email = 'xxxx'
#command template
command = (
'#!/bin/bash\n'
'##SBATCH --nodes=1 # redundant\n'
'#SBATCH --account={ACCOUNT}\n'
'#SBATCH --partition=shared\n'
'#SBATCH -N 1 # Ensure that all cores are on one machine\n'
'#SBATCH --ntasks=1\n'
'#SBATCH --cpus-per-task={NUM_CPU}\n'
'#SBATCH -t 0-5:00 # Runtime in D-HH:MM\n'
'##SBATCH --mem=124000 # Memory pool for all cores (see also --mem-per-cpu) SHOULD NOT BE USED\n'
'#SBATCH -o EXC%a # File to which STDOUT will be written\n'
'#SBATCH -e EXCErr%a # File to which STDERR will be written\n'
'#SBATCH --job-name=EXC\n'
'#SBATCH --mail-type=FAIL # Type of email notification- BEGIN,END,FAIL,ALL\n'
'#SBATCH --mail-user={EMAIL} # Email to which notifications will be sent\n'
'#SBATCH --array=1-1%1\n'
'### Set this to the working directory\n\n'
'{CMD}\n')
#replace
command = command.replace('{NUM_CPU}',str(numCPU))
command = command.replace('{CMD}',cmd)
command = command.replace('{ACCOUNT}',account)
command = command.replace('{EMAIL}',email)
command = command.replace('{USERNAME}',username)
#write to file
fout = open('exc.sh','w')
fout.write(command)
fout.close()
#submit to sbatch
os.system('sbatch exc.sh')
#remove temp file
os.system('rm exc.sh')
EXCB: Same thing but allows you to specify a list of commands in a separate text file. This “jobs” file is then executed as a job array.
#!/usr/bin/python
import os
import sys
#input checking
if(len(sys.argv)!=4):
print "USAGE: python excb.py [NUM_CPU] [JOB_FILE_LIST] [JOB_BATCH_SIZE]"
sys.exit()
numCPU = int(sys.argv[1])
if(numCPU > 24):
print "ERROR: Only 24 CPUs on a node."
sys.exit()
jobFile = sys.argv[2]
batchSize = sys.argv[3]
if(batchSize!='A'):
batchSize=int(batchSize)
if(batchSize!='A' and batchSize > 75):
print "ERROR: Batch size limit exceeded."
sys.exit()
#params
account = 'xxxx'
username = 'xxxx'
email = 'xxxx'
#figure out number of lines in job file
fin = open(jobFile,'r')
numl = 0
for line in fin:
numl = numl + 1
fin.close()
if(batchSize=='A'):
batchSize=numl
#command template
command = (
'#!/bin/bash\n'
'##SBATCH --nodes=1 # redundant\n'
'#SBATCH --account={ACCOUNT}\n'
'#SBATCH --partition=shared\n'
'#SBATCH -N 1 # Ensure that all cores are on one machine\n'
'#SBATCH --ntasks=1\n'
'#SBATCH --cpus-per-task={NUM_CPU}\n'
'#SBATCH -t 0-7:00 # Runtime in D-HH:MM\n'
'##SBATCH --mem=124000 # Memory pool for all cores (see also --mem-per-cpu) SHOULD NOT BE USED\n'
'#SBATCH -o EXCB%a # File to which STDOUT will be written\n'
'#SBATCH -e EXCBErr%a # File to which STDERR will be written\n'
'#SBATCH --job-name=EXCB\n'
'#SBATCH --mail-type=FAIL # Type of email notification- BEGIN,END,FAIL,ALL\n'
'#SBATCH --mail-user={EMAIL} # Email to which notifications will be sent\n'
'#SBATCH --array=1-{NUML}%{BATCH_SIZE}\n'
'### Set this to the working directory\n\n'
'linevar=`sed $SLURM_ARRAY_TASK_ID\'q;d\' {CMD}`\n'
'eval $linevar')
#replace
command = command.replace('{NUM_CPU}',str(numCPU))
command = command.replace('{CMD}',jobFile)
command = command.replace('{NUML}',str(numl))
command = command.replace('{BATCH_SIZE}',str(batchSize))
command = command.replace('{ACCOUNT}',account)
command = command.replace('{EMAIL}',email)
command = command.replace('{USERNAME}',username)
#write to file
fout = open('excb.sh','w')
fout.write(command)
fout.close()
#submit to sbatch
os.system('sbatch excb.sh')
#remove temp file
os.system('rm excb.sh')
A lot of people have recently been asking me about help with the SLURM system at UCSD, so I decided to write a blog post to help people quickly learn how to use it and get their jobs running. I have a simple script that can be executed via the sbatch command that forks jobs in a job array. This allows you to run multiple of the same jobs in parallel on the cluster.
So say you have a bunch of scripts you want to run in parallel on a SLURM system. We can put all the script commands into a file (calls.txt):
calls.txt:
script1.sh
script2.sh
script3.sh
Then we can create an sbatch script that specifies a job array that runs through these commands and executes them in a parallel job array. Here is the job array script for sbatch (runTest.sh):
runTest.sh:
#!/bin/bash
#SBATCH --account=xxxx
#SBATCH --partition=shared
#SBATCH -N 1 # Ensure that all cores are on one machine
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=1
#SBATCH -t 0-00:10 # Runtime in D-HH:MM
#SBATCH -o outputfile%a # File to which STDOUT will be written
#SBATCH -e outputerr%a # File to which STDERR will be written
#SBATCH --job-name=TestJob
#SBATCH --mail-type=ALL # Type of email notification- BEGIN,END,FAIL,ALL
#SBATCH --mail-user=xxxx@ucsd.edu # Email to which notifications will be sent
#SBATCH --array=1-3%3
linevar=`sed $SLURM_ARRAY_TASK_ID'q;d' calls.txt`
eval $linevar
As one can see, the sbatch script has several parameters. Some of the useful ones that one should specify:
account: The university PI account on SLURM (different for each lab)
partition: shared vs. compute. “shared” is generally what people use if you just want to use the cluster for straight-forward jobs. “compute” specifies a more reserved use of the cluster that needs more time (but also costs more).
nodes: specifies how many nodes to use (each node has 24 cores)
ntasks-per-node: how many tasks there are (in this case, I’m treating this all as 1 task).
cpus-per-task: How many cores to use per task in the job array.
runtime (how long to run any 1 job). Runtime is specified in D-HH:MM
-o specifies that outputfiles and -e specifies error files. You can just keep these as is for now (and change once you try running it if need be).
SLURM has the option of sending you email notifications. See comments in script
array=1-3%3 specifies that the job array contains three jobs (i.e. calls.txt has three lines) and %3 specifies they should be run 3 at a time (i.e. all at once). If you have 50 jobs you want to run 10 at a time, the command is array=1-50%10.
All the job array script does is step through calls.txt and fork them to the cluster in batches that are specified by the “array” command.
Then on Comet/TSCC,all one has to do is:
sbatch runTest.sh
You can do the following command to check the status of your job array in the Comet or TSSC queue:
squeue -u yourusername
Hopefully this makes use of SLURM a lot simpler for everyone. Cheers!