Pokemon Card Recognizer Now Live on PyPi!

Release available at: https://pypi.org/project/pokemon-card-recognizer/?fbclid=IwAR3EuvXrQRoPpWwpYT8Mgp025FM-nYt6lDYTJdAVtlNgJujN08hPesJzWxg

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!

Recognize a Pokemon card in an image or video:

from card_recognizer.api.card_recognizer import (
    CardRecognizer, Mode) 

recognizer = CardRecognizer(
    mode=Mode.PULLS_VIDEO
)
pulls = recognizer.exec("/path/to/video")

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?

Release available at: https://pypi.org/project/pokemon-card-recognizer/?fbclid=IwAR3EuvXrQRoPpWwpYT8Mgp025FM-nYt6lDYTJdAVtlNgJujN08hPesJzWxg

What is the origin of the vocal riff in Light’s “Prodigal Daughter” Track on the PEP album?

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:

Bollywood Lyric #Shazam Result(s)Google Music Result(s)
01*Morning Take Over (Original Mix) by Michael Vagas [https://www.shazam.com/track/72320353/morning-take-over-original-mix Terrorist]
*Dub by Goth Mountain [https://www.shazam.com/track/116816050/terrorist-dub]
Bollywood Vocal Ringtone (Ringtones Greatest Hits) by Sound Effects 2010
02Unreel 2 Real by Galactic Caravan [https://www.shazam.com/track/53859649/unreel-2-real]Indian Summer (Breathe) by Feder 2017
03
Unreel 2 Real by Galactic Caravan [https://www.shazam.com/track/53859649/unreel-2-real]
Tonight Only (Random Line) by Seo Young Do Electric Ensemble 2010
04Beats from Mumbai. by Waffle-O [https://www.shazam.com/track/529898818/beats-from-mumbai]Beats from Mumbai. by Waffle-O
05For The Sake Of Distant Days by Frank Hermans [https://www.shazam.com/track/290835214/for-the-sake-of-distant-days]No Result
06No ResultSonic Jams (Sonic Jams) by J. Etienne 2020
07No ResultNo Result
08Eastern Dreams (Bonus Cool Down 2) by Power Music Workout [https://www.shazam.com/track/200637314/eastern-dreams-bonus-cool-down-2]Sonic Jams (Sonic Jams) by J. Etienne 2020
09No ResultNo Result
10SubCities by Northern Jaw [https://www.shazam.com/track/579016153/subcities]China (Tristano EP) by DJ Fox 2011
11When Is It Dull by LogDoc [https://www.shazam.com/track/380956505/when-is-it-dull]English Lit (No Cents) by Leth-R-Gic 2014
22Poooow by Aglubinatsch [https://www.shazam.com/track/580647164/poooow]Poooow by Aglubinatsch 2021

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.

Thus, I was not able to audio fingerprint the original singer using these services. Even though both Shazam and Google music claim to be usable on Bollywood music, having access to Indian music databases such as Saavn (https://www.firstpost.com/tech/news-analysis/shazam-and-saavn-team-up-for-discovery-of-indian-music-3622967.html), the recognition is mostly finding remixes of the loop, not the original recording.

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:

https://thunderpussy.com/UPC/4260216391217
https://downinthevalley.com/UPC/4260216391217
https://findersrecords.com/UPC/4260216391217
Format: Digital
Label: Music4License
Rel. Date: 08/27/2012
UPC: 4260216391217

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.

How much is your Pokemon booster box actually worth?

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.

Autogeneration of SLURM on Comet/TSCC

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')

 

Example SLURM Script for Comet/TSCC Systems

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!