Taggerscript + Plugin: Separating performers by instrument

I wanted to share a taggerscript to address issues that many people likely share with the default Picard behavior for saving artist performance relationships:

  1. My preferred MP3 players cannot read TMCL and IPLS frames
  2. I find the default parentheses formatting to be extremely noisy and difficult to read, so I’d prefer to separate the performers by instrument into dedicated fields.

Here’s a demonstration:

Before:
image
After:
image

For the current version of the script, see this post. Hope others enjoy this as much as I will.

It used to be a pretty simple script that just requires the “Instruments” plugin by David Mandelberg, but it has a variety of bugs due to the way MusicBrainz and Picard work. The bug-filled original script is posted here so the simplicity of the concept can be seen:

$foreach(%_instruments%,
  $set(_currentInstrument,%_loop_value%)

  $if($eq(%_currentInstrument%,other instruments),,
    $noop(Standardize instrument names to be used in tag field names)
    $set(_standardizedInstrument,$lower(%_currentInstrument%))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,drums \(drum set\),drums))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,membranophone,drums))

    $noop(Set custom field)
    $set(_currentCustomPerformerField,performer %_standardizedInstrument%)
    $set(_performerPattern,%_standardizedInstrument%)
    $setmulti(%_currentCustomPerformerField%,$performer(%_currentInstrument%,	),	)
  
    $noop(keep list of instruments so the tags can be scripted)
    $copymerge(_standardizedInstruments,_standardizedInstrument)
  )
)

$foreach($unique(%_standardizedInstruments%),
$set(_standardizedInstrument,%_loop_value%)
$copymerge(instruments,_standardizedInstrument)
)

$unset(performer:*)

Unfortunately, the quirks of MusicBrainz and Picard require more complexity. Again, see this post for the updated version of the script.

5 Likes

Hi! I made an account specially to reply to you, your script works very well, I was wondering if it would be possible to achieve something similar with the rest of the IPLS metadata (producer, engineer, etc), perhaps tweaking your original script? I really know close to nothing about scripting, I’m just trying to make foobar2000 display the IPLS field one way or another :confused:

1 Like

The original script has a variety of issues due to the way MusicBrainz and Picard work. In order to address all the issues I am observing in my library, the script becomes much more complicated. Due to the complexity, I will be posting my script as-is, without removing any of the proprietary personal tags that are present.

The updated script currently has additional requirements:

  1. You still need the “Instruments” plugin by David Mandelberg.
  2. You now need an additional plugin, rperformer, so exact match RegEx can be used. This is scheduled for Picard 2.7.
  3. You will need to manually apply this patch to rperformer if you use the colon in a pre-existing performer field. This bug fix is scheduled for Picard 2.7.

For the current version of the script, jump below. Apparently, I lose the ability to edit old posts.

Picard is case sensitive, so this is actually very easy:

$if($eq($upper(%_extension%),MP3),
$set(ARRANGER,%arranger%)
$unset(arranger)
)

In my testing, this creates a TXXX ARRANGER field rather than an INVOLVED PEOPLE entry.

I don’t think it really clicked for me that in order to get a unified view of data in foobar2000, you need to intentionally NOT have a unified view in Picard (since field names are case-sensitive). I’ll have to rewrite all of my userscripts to change the capitalization based on file extension…

1 Like

I have updated the script to address a variety of bugs/features from MusicBrainz data and Picard.

1 Like

For those who have not been following, I have been adding a series of performer name standardizations for Japanese credits. Currently,

  1. Removing the character in front of the CV/cv anisong delimiter (requires a colon or period for safety)
  2. Removing the character in front of the “starring” anisong delimiter
  3. Removing the leading BEMANI Sound Team / Konami Amusement / Konami Digital Entertainment moniker in front of the person

The script (NOTE: This is no longer the current version of the script - for the current version, jump below):

$noop("instruments" and "additional instruments" ends up in performer)
$unset(performer)

$set(_instrumentsFieldName,instruments)
  $noop(Picard is case sensitive, so MP3 TXXX tags must be manually handled)
  $if($eq_any($upper(%_extension%),MP3),$set(_instrumentsFieldName,$upper(%_instrumentsFieldName%)))

$noop(I like to indicate whether these are track-level, release-level, or 'reduction by ear' credits. You need to manually fill this in.)
$set(_instrumentsPrecisionField,instruments precision)
  $noop(Picard is case sensitive, so MP3 TXXX tags must be manually handled)
  $if($eq_any($upper(%_extension%),MP3),$set(_instrumentsPrecisionField,$upper(%_instrumentsPrecisionField%)))



$foreach(%_instruments%,
  $set(_currentInstrument,%_loop_value%)

  $noop(Ignore misuse of instrument 0a06dd9a-92d6-4891-a699-2b116a3d3f37)
  $if($eq($lower(%_currentInstrument%),other instruments),$set(_skipInstrument,1))
  $if($eq($lower(%_currentInstrument%),all other instruments),$set(_skipInstrument,1))
  $if($eq($lower(%_currentInstrument%),all other instruments & programming),$set(_skipInstrument,1))

  $if($eq(%_skipInstrument%,1),,
    $noop(Standardize instrument names to be used in tag field names)
    $set(_standardizedInstrument,$lower(%_currentInstrument%))
    $noop(Transliterate the field name for non-ASCII instruments)
      $noop(e.g., bandoneón)
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,ó,o))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,ギター,guitar))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,鍵盤ハーモニカ,melodica))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,二胡,erhu))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,尺八,shakuhachi))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,三味線,shamisen))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,琴,koto))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,能管,nohkan))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,篠笛,shinobue))
      $noop(Note that 笛 doesn't always mean flute - it might be whistling vocals!)
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,笛,flute))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,スキャット,scat))


    $noop(Migrate legacy data)
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,drums \(drum set\),drums))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,membranophone,drums))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,guitar family,guitar))

    $noop(Standardize credited names)
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,1st violin,violin))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,2nd violin,violin))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,3rd violin,violin))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,violin family,violin))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,violins,violin))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,violoncello,cello))

    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,vocals,vocal))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,lead vocal,vocal))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,rapper,rap))

    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,backing chorus,background vocal))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,fantastic chorus,background vocal))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,chorus,background vocal))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,background vocal master,chorus master))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,backing vocal,background vocal))

    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,guitars,guitar))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,e.guitar,electric guitar))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,a.guitar,acoustic guitar))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,w.bass,wood bass))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,a.saxophone,alto saxophone))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,b.saxophone,baritone saxophone))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,t.saxophone,tenor saxophone))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,pf,piano))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,keyboards,keyboard))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,synthesizers,synthesizer))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,percussions,percussion))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,mini moog,minimoog))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,blues harp,harmonica))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,prophet-5,analog synthesizer))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,fagotto,bassoon))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,fagott,bassoon))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,tsugarushamisen,shamisen))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,cor anglais,oboe))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,english horn,oboe))


    $noop(Set custom field's name)
    $set(_currentCustomPerformerField,performer %_standardizedInstrument%)
      $noop(Picard is case sensitive, so MP3 TXXX tags must be manually handled)
      $if($eq($upper(%_extension%),MP3),$set(_currentCustomPerformerField,$upper(%_currentCustomPerformerField%)))

    $noop(If I set the instruments using 'reduction by ear', then don't download non-applicable performers.)
    $set(_existingInstruments,$get(%_instrumentsFieldName%))
    $set(_instruments_precision,$get(%_instrumentsPrecisionField%))
    $if($eq(%_instruments_precision%,reduction by ear),
      $if($find(%_existingInstruments%,%_standardizedInstrument%),,
        $set(_skipInstrument,1)
      )
    )

    $if($eq(%_skipInstrument%,1),,
      $noop(Performer prefixes)
      $foreach(; additional ; guest ; solo ; guest solo ,
        $set(_currentInstrumentRegex,^\(.*\, \)?\(.* and \)?%_loop_value%$replace($replace(%_currentInstrument%,\(,\\\(),\),\\\))\(\, .*\)?\( and .*\)?\$)
        $setmulti(_currentInstrumentMains,$rperformer(%_currentInstrumentRegex%,	),	)
        $foreach($unique(%_currentInstrumentMains%),
          $set(_performer,%_loop_value%)

          $noop(Standardize the musician names here, since it's not really possible to work on the performer names elsewhere)

          $noop(Undo select fancy punctuation)
          $set(_performer,$replace($get(_performer),‐,-))
          $set(_performer,$replace($get(_performer),“,"))
          $set(_performer,$replace($get(_performer),”,"))
          $set(_performer,$replace($get(_performer),’,'))
  
          $noop(Remove character from the vocal in CV credited names)
          $if($or($find(%_performer%,\(CV:),$find(%_performer%,\(CV.)),
            $set(_performer,$rreplace(%_performer%,\(.*\)\\\(CV[.:]\(.*\)\\\),\\2))
          )
          $noop(...lowercase cv)
          $if($or($find(%_performer%,\(cv:),$find(%_performer%,\(cv.)),
            $set(_performer,$rreplace(%_performer%,\(.*\)\\\(cv[.:]\(.*\)\\\),\\2))
          )
          $noop(Remove character from the vocal in Geneon-style starring credited names)
          $if($find(%_performer%, starring ),
            $set(_performer,$rreplace(%_performer%,\(.*\) starring \(.*\),\\2))
          )
          $noop(Remove BEMANI Sound Team)
          $if($find(%_performer%,BEMANI Sound Team),
            $set(_performer,$rreplace(%_performer%,BEMANI Sound Team ["“”]\(.*\)["“”],\\1))
          )
          $noop(Remove Konami Amusement)
          $if($find(%_performer%,Konami Amusement),
            $set(_performer,$rreplace(%_performer%,Konami Amusement \\\(\(.*\)\\\),\\1))
          )
          $noop(Remove Konami Digital Entertainment)
          $if($find(%_performer%,Konami Digital Entertainment),
            $set(_performer,$rreplace(%_performer%,Konami Digital Entertainment \\\(\(.*\)\\\),\\1))
          )
  
          $copymerge(%_currentCustomPerformerField%,_performer)
        )$noop(Close foreach performer in this performer prefix)
      )$noop(Close foreach performer prefix)
  
      $noop(keep list of instruments so the tags can be scripted)
      $copymerge(_standardizedInstruments,_standardizedInstrument)
    )
  )

  $set(_skipInstrument,)
)$noop(Close foreach _instruments)

$noop(Save instruments, removing any local instruments that MusicBrainz doesn't know about)
$delete(%_instrumentsFieldName%)
$foreach($unique(%_standardizedInstruments%),
  $set(_standardizedInstrument,%_loop_value%)
  $copymerge(%_instrumentsFieldName%,_standardizedInstrument)

  $noop(Flatten M4A performer tags: Mutagen writes multi-value tags that can't be read correctly by foobar2000, Mp3tag, etc.)
  $if($eq($upper(%_extension%),M4A),
    $noop(Set custom field's name)
    $set(_currentCustomPerformerField,performer %_standardizedInstrument%)
    $set(%_currentCustomPerformerField%,$join($get(%_currentCustomPerformerField%),; ))
  )
)
$noop(Flatten M4A instruments tag: Mutagen writes multi-value tags that can't be read correctly by foobar2000, Mp3tag, etc.)
$if($eq($upper(%_extension%),M4A),
  $set(instruments,$join(%instruments%,; ))
)

$unset(performer:*)

$noop(I like to indicate whether these are track-level, release-level, or 'reduction by ear' credits. You need to manually fill this in.)
$set(_instruments_precision,$get(%_instrumentsPrecisionField%))
$if($and($gt($lenmulti(%_instruments%),0),$eq(0,$len(%_instruments_precision%))),
$set(%_instrumentsPrecisionField%,?)
)

I have modified the script to mirror data from the server to the local file. This makes the current server data the source of truth, since in theory, these instrument/performer tags aren’t supposed to be hand-edited, and any removals in MusicBrainz is the correction of user error. (Previously, the behavior of the script was to merge new server data into the local files without ever deleting anything, which would leave incorrect data in the local file that had been removed from the server.) The script now removes both individual performer values and entire performer fields.

Script for Picard 2.6.4:

  1. You need to install the “Instruments” plugin by David Mandelberg.
  2. You need to install the additional plugin, rperformer, so exact match RegEx can be used. Additionally, you need to manually apply this patch to rperformer if you use the colon in a pre-existing performer field. For an easier time, upgrade to Picard 2.7.0.

(NOTE: This is no longer the current version of the script - for the current version, jump to the bottom.)

$noop(Separating performers by instrument for Picard 2.6.4 w/ Instruments plugin and \$rperformer plugin)

$noop("instruments" and "additional instruments" ends up in performer)
$unset(performer)

$set(_instrumentsFieldName,instruments)
  $noop(Picard is case sensitive, so MP3 TXXX tags must be manually handled)
  $if($eq_any($upper(%_extension%),MP3),$set(_instrumentsFieldName,$upper(%_instrumentsFieldName%)))

$noop(I like to indicate whether these are track-level, release-level, or 'reduction by ear' credits. You need to manually fill this in.)
$set(_instrumentsPrecisionField,instruments precision)
  $noop(Picard is case sensitive, so MP3 TXXX tags must be manually handled)
  $if($eq_any($upper(%_extension%),MP3),$set(_instrumentsPrecisionField,$upper(%_instrumentsPrecisionField%)))



$foreach(%_instruments%,
  $set(_currentInstrument,%_loop_value%)

  $noop(Ignore misuse of instrument 0a06dd9a-92d6-4891-a699-2b116a3d3f37)
  $if($eq($lower(%_currentInstrument%),other instruments),$set(_skipInstrument,1))
  $if($eq($lower(%_currentInstrument%),all other instruments),$set(_skipInstrument,1))
  $if($eq($lower(%_currentInstrument%),all other instruments & programming),$set(_skipInstrument,1))

  $if($eq(%_skipInstrument%,1),,
    $noop(Standardize instrument names to be used in tag field names)
    $set(_standardizedInstrument,$lower(%_currentInstrument%))
    $noop(Transliterate the field name for non-ASCII instruments)
      $noop(e.g., bandoneón)
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,ó,o))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,ギター,guitar))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,鍵盤ハーモニカ,melodica))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,二胡,erhu))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,尺八,shakuhachi))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,三味線,shamisen))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,琴,koto))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,能管,nohkan))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,篠笛,shinobue))
      $noop(Note that 笛 doesn't always mean flute - it might be whistling vocals!)
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,笛,flute))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,ファゴット,bassoon))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,コントラファゴット,contrabassoon))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,スキャット,scat))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,コーラス,chorus))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,かけ声,shout))


    $noop(Migrate legacy data)
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,drums \(drum set\),drums))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,membranophone,drums))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,guitar family,guitar))

    $noop(Standardize credited names)
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,1st violin,violin))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,2nd violin,violin))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,3rd violin,violin))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,violin family,violin))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,violins,violin))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,violoncello,cello))

    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,vocals,vocal))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,lead vocal,vocal))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,rapper,rap))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,backing chorus,background vocal))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,fantastic chorus,background vocal))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,chorus,background vocal))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,background vocal master,chorus master))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,backing vocal,background vocal))

    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,guitars,guitar))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,e.guitar,electric guitar))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,a.guitar,acoustic guitar))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,w.bass,wood bass))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,a.saxophone,alto saxophone))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,b.saxophone,baritone saxophone))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,t.saxophone,tenor saxophone))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,sax section,sax))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,pf,piano))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,keyboards,keyboard))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,synthesizers,synthesizer))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,percussions,percussion))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,mini moog,minimoog))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,blues harp,harmonica))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,prophet-5,analog synthesizer))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,fagotto,bassoon))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,fagott,bassoon))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,tsugarushamisen,shamisen))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,cor anglais,oboe))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,english horn,oboe))


    $noop(Set custom field's name)
    $set(_currentCustomPerformerField,performer %_standardizedInstrument%)
      $noop(Picard is case sensitive, so MP3 TXXX tags must be manually handled)
      $if($eq($upper(%_extension%),MP3),$set(_currentCustomPerformerField,$upper(%_currentCustomPerformerField%)))
    $set(_temp_currentCustomPerformerField,temp performer %_standardizedInstrument%)

    $noop(If I set the instruments using 'reduction by ear', then don't download non-applicable performers.)
    $set(_existingInstruments,$get(%_instrumentsFieldName%))
    $set(_instruments_precision,$get(%_instrumentsPrecisionField%))
    $if($eq(%_instruments_precision%,reduction by ear),
      $if($find(%_existingInstruments%,%_standardizedInstrument%),,
        $set(_skipInstrument,1)
      )
    )

    $if($eq(%_skipInstrument%,1),,
      $noop(Performer prefixes)
      $foreach(; additional ; guest ; solo ; guest solo ,
        $set(_currentInstrumentRegex,^\(.*\, \)?\(.* and \)?%_loop_value%$replace($replace(%_currentInstrument%,\(,\\\(),\),\\\))\(\, .*\)?\( and .*\)?\$)
        $setmulti(_currentInstrumentMains,$rperformer(%_currentInstrumentRegex%,	),	)
        $foreach($unique(%_currentInstrumentMains%),
          $set(_performer,%_loop_value%)

          $noop(Standardize the musician names here, since it's not really possible to work on the performer names elsewhere)

          $noop(Undo select fancy punctuation)
          $set(_performer,$replace($get(_performer),‐,-))
          $set(_performer,$replace($get(_performer),“,"))
          $set(_performer,$replace($get(_performer),”,"))
          $set(_performer,$replace($get(_performer),’,'))
  
          $noop(Remove character from the vocal in CV credited names)
          $if($rsearch(%_performer%,[(\\\(][CcCc][\\..]{0\,1}[VvVv][:\\.:.\\s]),
            $set(_performer,$rreplace(%_performer%,\(.*\)\\s*\([(\\\(]\)\([CcCc][\\..]{0\,1}[VvVv]\)\([:\\.:.]\)\\s*\(.*\)\([)\\\)]\),\\5))
          )
          $noop(Remove character from the vocal in Geneon-style starring credited names)
          $if($find(%_performer%, starring ),
            $set(_performer,$rreplace(%_performer%,\(.*\) starring \(.*\),\\2))
          )
          $noop(Remove BEMANI Sound Team)
          $if($find(%_performer%,BEMANI Sound Team),
            $set(_performer,$rreplace(%_performer%,BEMANI Sound Team ["“”]\(.*\)["“”],\\1))
          )
          $noop(Remove Konami Amusement)
          $if($find(%_performer%,Konami Amusement),
            $set(_performer,$rreplace(%_performer%,Konami Amusement \\\(\(.*\)\\\),\\1))
          )
          $noop(Remove Konami Digital Entertainment)
          $if($find(%_performer%,Konami Digital Entertainment),
            $set(_performer,$rreplace(%_performer%,Konami Digital Entertainment \\\(\(.*\)\\\),\\1))
          )

          $copymerge(%_temp_currentCustomPerformerField%,_performer)
        )$noop(Close foreach performer in this performer prefix)
      )$noop(Close foreach performer prefix)

      $noop(Merge conflicts - remove local values not found in the server; add server values not found in local)
      $set(_temp_ordered_currentCustomPerformerValues,)
      $foreach($get(%_currentCustomPerformerField%),
        $set(_oldPerformerValue,%_loop_value%)
        $set(_foundOldPerformerValue,0)
        $foreach($unique($get(%_temp_currentCustomPerformerField%)),
          $if($eq(%_loop_value%,%_oldPerformerValue%),$set(_foundOldPerformerValue,1),)
        )
        $if($eq(%_foundOldPerformerValue%,1),$copymerge(_temp_ordered_currentCustomPerformerValues,_oldPerformerValue),)
      )

      $if(%_currentCustomPerformerField%,$delete(%_currentCustomPerformerField%))
      $noop(Add old values that I may have manually ordered)
      $copymerge(%_currentCustomPerformerField%,_temp_ordered_currentCustomPerformerValues)
      $noop(Add new values not found in my local tag at the end)
      $copymerge(%_currentCustomPerformerField%,%_temp_currentCustomPerformerField%)

      $if(%_temp_currentCustomPerformerField%,$delete(%_temp_currentCustomPerformerField%))
      $if(%_temp_ordered_currentCustomPerformerValues%,$unset(%_temp_ordered_currentCustomPerformerValues%))

      $noop(keep list of instruments so the tags can be scripted)
      $copymerge(_standardizedInstruments,_standardizedInstrument)
    )
  )

  $set(_skipInstrument,)
)$noop(Close foreach _instruments)

$noop(Delete any local performer fields that the server doesn't know about following name standardization)
$foreach($unique($get(%_instrumentsFieldName%)),
  $set(_currentCustomPerformerField,performer %_loop_value%)
  $noop(Picard is case sensitive, so MP3 TXXX tags must be manually handled)
  $if($eq_any($upper(%_extension%),MP3),$set(_currentCustomPerformerField,$upper(%_currentCustomPerformerField%)))

  $if($find(%_standardizedInstruments%,%_loop_value%),,$delete(%_currentCustomPerformerField%))
)

$noop(Save instruments, removing any local instruments that MusicBrainz doesn't know about)
$delete(%_instrumentsFieldName%)
$foreach($unique(%_standardizedInstruments%),
  $set(_standardizedInstrument,%_loop_value%)
  $copymerge(%_instrumentsFieldName%,_standardizedInstrument)

  $noop(Flatten M4A performer tags: Mutagen writes multi-value tags that can't be read correctly by foobar2000, Mp3tag, etc.)
  $if($eq($upper(%_extension%),M4A),
    $noop(Set custom field's name)
    $set(_currentCustomPerformerField,performer %_standardizedInstrument%)
    $set(%_currentCustomPerformerField%,$join($get(%_currentCustomPerformerField%),; ))
  )
)
$noop(Flatten M4A instruments tag: Mutagen writes multi-value tags that can't be read correctly by foobar2000, Mp3tag, etc.)
$if($eq($upper(%_extension%),M4A),
  $set(instruments,$join(%instruments%,; ))
)

$unset(performer:*)

$noop(I like to indicate whether these are track-level, release-level, or 'reduction by ear' credits. You need to manually fill this in.)
$set(_instruments_precision,$get(%_instrumentsPrecisionField%))
$if($and($gt($lenmulti(%_instruments%),0),$eq(0,$len(%_instruments_precision%))),
$set(%_instrumentsPrecisionField%,?)
)

Script for Picard 2.7.0:

  1. You need to install the “Instruments” plugin by David Mandelberg.

(NOTE: This is no longer the current version of the script - for the current version, jump to the bottom.)

$noop(Separating performers by instrument for Picard 2.7.0 w/ Instruments plugin)

$noop("instruments" and "additional instruments" ends up in performer)
$unset(performer)

$set(_instrumentsFieldName,instruments)
  $noop(Picard is case sensitive, so MP3 TXXX tags must be manually handled)
  $if($eq_any($upper(%_extension%),MP3),$set(_instrumentsFieldName,$upper(%_instrumentsFieldName%)))

$noop(I like to indicate whether these are track-level, release-level, or 'reduction by ear' credits. You need to manually fill this in.)
$set(_instrumentsPrecisionField,instruments precision)
  $noop(Picard is case sensitive, so MP3 TXXX tags must be manually handled)
  $if($eq_any($upper(%_extension%),MP3),$set(_instrumentsPrecisionField,$upper(%_instrumentsPrecisionField%)))



$foreach(%_instruments%,
  $set(_currentInstrument,%_loop_value%)

  $noop(Ignore misuse of instrument 0a06dd9a-92d6-4891-a699-2b116a3d3f37)
  $if($eq($lower(%_currentInstrument%),other instruments),$set(_skipInstrument,1))
  $if($eq($lower(%_currentInstrument%),all other instruments),$set(_skipInstrument,1))
  $if($eq($lower(%_currentInstrument%),all other instruments & programming),$set(_skipInstrument,1))

  $if($eq(%_skipInstrument%,1),,
    $noop(Standardize instrument names to be used in tag field names)
    $set(_standardizedInstrument,$lower(%_currentInstrument%))
    $noop(Transliterate the field name for non-ASCII instruments)
      $noop(e.g., bandoneón)
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,ó,o))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,ギター,guitar))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,鍵盤ハーモニカ,melodica))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,二胡,erhu))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,尺八,shakuhachi))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,三味線,shamisen))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,琴,koto))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,能管,nohkan))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,篠笛,shinobue))
      $noop(Note that 笛 doesn't always mean flute - it might be whistling vocals!)
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,笛,flute))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,ファゴット,bassoon))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,コントラファゴット,contrabassoon))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,スキャット,scat))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,コーラス,chorus))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,かけ声,shout))


    $noop(Migrate legacy data)
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,drums \(drum set\),drums))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,membranophone,drums))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,guitar family,guitar))

    $noop(Standardize credited names)
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,1st violin,violin))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,2nd violin,violin))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,3rd violin,violin))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,violin family,violin))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,violins,violin))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,violoncello,cello))

    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,vocals,vocal))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,lead vocal,vocal))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,rapper,rap))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,backing chorus,background vocal))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,fantastic chorus,background vocal))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,chorus,background vocal))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,background vocal master,chorus master))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,backing vocal,background vocal))

    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,guitars,guitar))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,e.guitar,electric guitar))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,a.guitar,acoustic guitar))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,w.bass,wood bass))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,a.saxophone,alto saxophone))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,b.saxophone,baritone saxophone))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,t.saxophone,tenor saxophone))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,sax section,sax))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,pf,piano))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,keyboards,keyboard))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,synthesizers,synthesizer))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,percussions,percussion))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,mini moog,minimoog))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,blues harp,harmonica))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,prophet-5,analog synthesizer))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,fagotto,bassoon))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,fagott,bassoon))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,tsugarushamisen,shamisen))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,cor anglais,oboe))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,english horn,oboe))


    $noop(Set custom field's name)
    $set(_currentCustomPerformerField,performer %_standardizedInstrument%)
      $noop(Picard is case sensitive, so MP3 TXXX tags must be manually handled)
      $if($eq($upper(%_extension%),MP3),$set(_currentCustomPerformerField,$upper(%_currentCustomPerformerField%)))
    $set(_temp_currentCustomPerformerField,temp performer %_standardizedInstrument%)

    $noop(If I set the instruments using 'reduction by ear', then don't download non-applicable performers.)
    $set(_existingInstruments,$get(%_instrumentsFieldName%))
    $set(_instruments_precision,$get(%_instrumentsPrecisionField%))
    $if($eq(%_instruments_precision%,reduction by ear),
      $if($find(%_existingInstruments%,%_standardizedInstrument%),,
        $set(_skipInstrument,1)
      )
    )

    $if($eq(%_skipInstrument%,1),,
      $noop(Performer prefixes)
      $foreach(; additional ; guest ; solo ; guest solo ,
        $set(_currentInstrumentRegex,/^\(.*\, \)?\(.* and \)?%_loop_value%$replace($replace(%_currentInstrument%,\(,\\\(),\),\\\))\(\, .*\)?\( and .*\)?\$/)
        $setmulti(_currentInstrumentMains,$performer(%_currentInstrumentRegex%,	),	)
        $foreach($unique(%_currentInstrumentMains%),
          $set(_performer,%_loop_value%)

          $noop(Standardize the musician names here, since it's not really possible to work on the performer names elsewhere)

          $noop(Undo select fancy punctuation)
          $set(_performer,$replace($get(_performer),‐,-))
          $set(_performer,$replace($get(_performer),“,"))
          $set(_performer,$replace($get(_performer),”,"))
          $set(_performer,$replace($get(_performer),’,'))
  
          $noop(Remove character from the vocal in CV credited names)
          $if($rsearch(%_performer%,[(\\\(][CcCc][\\..]{0\,1}[VvVv][:\\.:.\\s]),
            $set(_performer,$rreplace(%_performer%,\(.*\)\\s*\([(\\\(]\)\([CcCc][\\..]{0\,1}[VvVv]\)\([:\\.:.]\)\\s*\(.*\)\([)\\\)]\),\\5))
          )
          $noop(Remove character from the vocal in Geneon-style starring credited names)
          $if($find(%_performer%, starring ),
            $set(_performer,$rreplace(%_performer%,\(.*\) starring \(.*\),\\2))
          )
          $noop(Remove BEMANI Sound Team)
          $if($find(%_performer%,BEMANI Sound Team),
            $set(_performer,$rreplace(%_performer%,BEMANI Sound Team ["“”]\(.*\)["“”],\\1))
          )
          $noop(Remove Konami Amusement)
          $if($find(%_performer%,Konami Amusement),
            $set(_performer,$rreplace(%_performer%,Konami Amusement \\\(\(.*\)\\\),\\1))
          )
          $noop(Remove Konami Digital Entertainment)
          $if($find(%_performer%,Konami Digital Entertainment),
            $set(_performer,$rreplace(%_performer%,Konami Digital Entertainment \\\(\(.*\)\\\),\\1))
          )

          $copymerge(%_temp_currentCustomPerformerField%,_performer)
        )$noop(Close foreach performer in this performer prefix)
      )$noop(Close foreach performer prefix)

      $noop(Merge conflicts - remove local values not found in the server; add server values not found in local)
      $set(_temp_ordered_currentCustomPerformerValues,)
      $foreach($get(%_currentCustomPerformerField%),
        $set(_oldPerformerValue,%_loop_value%)
        $set(_foundOldPerformerValue,0)
        $foreach($unique($get(%_temp_currentCustomPerformerField%)),
          $if($eq(%_loop_value%,%_oldPerformerValue%),$set(_foundOldPerformerValue,1),)
        )
        $if($eq(%_foundOldPerformerValue%,1),$copymerge(_temp_ordered_currentCustomPerformerValues,_oldPerformerValue),)
      )

      $if(%_currentCustomPerformerField%,$delete(%_currentCustomPerformerField%))
      $noop(Add old values that I may have manually ordered)
      $copymerge(%_currentCustomPerformerField%,_temp_ordered_currentCustomPerformerValues)
      $noop(Add new values not found in my local tag at the end)
      $copymerge(%_currentCustomPerformerField%,%_temp_currentCustomPerformerField%)

      $if(%_temp_currentCustomPerformerField%,$delete(%_temp_currentCustomPerformerField%))
      $if(%_temp_ordered_currentCustomPerformerValues%,$unset(%_temp_ordered_currentCustomPerformerValues%))

      $noop(keep list of instruments so the tags can be scripted)
      $copymerge(_standardizedInstruments,_standardizedInstrument)
    )
  )

  $set(_skipInstrument,)
)$noop(Close foreach _instruments)

$noop(Delete any local performer fields that the server doesn't know about following name standardization)
$foreach($unique($get(%_instrumentsFieldName%)),
  $set(_currentCustomPerformerField,performer %_loop_value%)
  $noop(Picard is case sensitive, so MP3 TXXX tags must be manually handled)
  $if($eq_any($upper(%_extension%),MP3),$set(_currentCustomPerformerField,$upper(%_currentCustomPerformerField%)))

  $if($find(%_standardizedInstruments%,%_loop_value%),,$delete(%_currentCustomPerformerField%))
)

$noop(Save instruments, removing any local instruments that MusicBrainz doesn't know about)
$delete(%_instrumentsFieldName%)
$foreach($unique(%_standardizedInstruments%),
  $set(_standardizedInstrument,%_loop_value%)
  $copymerge(%_instrumentsFieldName%,_standardizedInstrument)

  $noop(Flatten M4A performer tags: Mutagen writes multi-value tags that can't be read correctly by foobar2000, Mp3tag, etc.)
  $if($eq($upper(%_extension%),M4A),
    $noop(Set custom field's name)
    $set(_currentCustomPerformerField,performer %_standardizedInstrument%)
    $set(%_currentCustomPerformerField%,$join($get(%_currentCustomPerformerField%),; ))
  )
)
$noop(Flatten M4A instruments tag: Mutagen writes multi-value tags that can't be read correctly by foobar2000, Mp3tag, etc.)
$if($eq($upper(%_extension%),M4A),
  $set(instruments,$join(%instruments%,; ))
)

$unset(performer:*)

$noop(I like to indicate whether these are track-level, release-level, or 'reduction by ear' credits. You need to manually fill this in.)
$set(_instruments_precision,$get(%_instrumentsPrecisionField%))
$if($and($gt($lenmulti(%_instruments%),0),$eq(0,$len(%_instruments_precision%))),
$set(%_instrumentsPrecisionField%,?)
)
1 Like

Updated the CV artist detection based on Taggerscript: Standardize Japanese CV artist credit whitespace and punctuation

Last updated 2022-07-25.

Script for Picard 2.7.0:

  1. You need to install the “Instruments” plugin by David Mandelberg.
$noop(Separating performers by instrument for Picard 2.7.0 w/ Instruments plugin)

$noop("instruments" and "additional instruments" ends up in performer)
$unset(performer)

$set(_instrumentsFieldName,instruments)
  $noop(Picard is case sensitive, so MP3 TXXX tags must be manually handled - Picard apparently reads ALLCAPS m4a tags as lower case...)
  $if($eq_any($upper(%_extension%),MP3),$set(_instrumentsFieldName,$upper(%_instrumentsFieldName%)))

$noop(I like to indicate whether these are track-level, release-level, or 'reduction by ear' credits. You need to manually fill this in.)
$set(_instrumentsPrecisionField,instruments precision)
  $noop(Picard is case sensitive, so MP3 TXXX tags must be manually handled - Picard apparently reads ALLCAPS m4a tags as lower case...)
  $if($eq_any($upper(%_extension%),MP3),$set(_instrumentsPrecisionField,$upper(%_instrumentsPrecisionField%)))



$foreach(%_instruments%,
  $set(_currentInstrument,%_loop_value%)

  $noop(Ignore misuse of instrument 0a06dd9a-92d6-4891-a699-2b116a3d3f37)
  $if($eq($lower(%_currentInstrument%),other instruments),$set(_skipInstrument,1))
  $if($eq($lower(%_currentInstrument%),all other instruments),$set(_skipInstrument,1))
  $if($eq($lower(%_currentInstrument%),all other instruments & programming),$set(_skipInstrument,1))

  $if($eq(%_skipInstrument%,1),,
    $noop(Standardize instrument names to be used in tag field names)
    $set(_standardizedInstrument,$lower(%_currentInstrument%))
    $noop(Transliterate the field name for non-ASCII instruments)
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,irish harp / clàrsach,clarsach))
      $noop(e.g., bandoneón)
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,ó,o))
      $noop(e.g., agogô)
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,ô,o))
      $noop(e.g., clàrsach)
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,à,a))
      $noop(For compatibility, don't want any apostrophes in field names.)
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,',_))

      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,ギター,guitar))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,鍵盤ハーモニカ,melodica))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,二胡,erhu))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,尺八,shakuhachi))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,三味線,shamisen))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,琴,koto))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,能管,nohkan))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,篠笛,shinobue))
      $noop(Note that 笛 doesn't always mean flute - it might be whistling vocals!)
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,笛,flute))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,コントラファゴット,contrabassoon))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,ファゴット,bassoon))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,スキャット,scat))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,コーラス,chorus))
      $set(_standardizedInstrument,$replace(%_standardizedInstrument%,かけ声,shout))


    $noop(Fix effectively-destructive edits to legacy data)
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,membranophone,drums))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,romantic guitar,gut guitar))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,guitar family,guitar))

    $noop(Standardize credited names)
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,drums \(drum set\),drums))

    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,1st violin,violin))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,2nd violin,violin))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,3rd violin,violin))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,violin family,violin))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,violins,violin))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,violoncello,cello))

    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,vocals,vocal))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,lead vocal,vocal))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,rapper,rap))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,sub vocal,background vocal))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,sub chorus,background vocal))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,backing chorus,background vocal))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,fantastic chorus,background vocal))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,cho.,chorus))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,chorus,background vocal))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,background vocal master,chorus master))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,backing vocal,background vocal))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,vocal samples,vocal sample))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,vocal sample,vocal))

    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,guitars,guitar))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,e.guitar,electric guitar))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,a.guitar,acoustic guitar))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,w.bass,wood bass))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,a.saxophone,alto saxophone))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,b.saxophone,baritone saxophone))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,t.saxophone,tenor saxophone))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,sax section,sax))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,fagotto,bassoon))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,fagott,bassoon))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,tsugarushamisen,shamisen))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,cor anglais,oboe))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,english horn,oboe))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,percussions,percussion))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,pf,piano))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,keyboards,keyboard))

    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,synthesizers,synthesizer))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,mini moog,minimoog))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,blues harp,harmonica))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,prophet-5,analog synthesizer))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,sub 37,analog synthesizer))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,dx-7,synthesizer))
    $set(_standardizedInstrument,$replace(%_standardizedInstrument%,emulator ii,synthesizer))



    $noop(Set custom field's name)
    $set(_currentCustomPerformerField,performer %_standardizedInstrument%)
      $noop(Picard is case sensitive, so MP3 TXXX tags must be manually handled - Picard apparently reads ALLCAPS m4a tags as lower case...)
      $if($eq_any($upper(%_extension%),MP3),$set(_currentCustomPerformerField,$upper(%_currentCustomPerformerField%)))
    $set(_temp_currentCustomPerformerField,temp performer %_standardizedInstrument%)

    $noop(If I set the instruments using 'reduction by ear', then don't download non-applicable performers.)
    $set(_existingInstruments,$get(%_instrumentsFieldName%))
    $set(_instruments_precision,$get(%_instrumentsPrecisionField%))
    $if($eq(%_instruments_precision%,reduction by ear),
      $if($find(%_existingInstruments%,%_standardizedInstrument%),,
        $set(_skipInstrument,1)
      )
    )

    $if($eq(%_skipInstrument%,1),,
      $noop(Performer prefixes)
      $foreach(; additional ; guest ; solo ; guest solo ,
        $set(_currentInstrumentRegex,/^\(.*\, \)?\(.* and \)?%_loop_value%$replace($replace(%_currentInstrument%,\(,\\\(),\),\\\))\(\, .*\)?\( and .*\)?\$/)
        $setmulti(_currentInstrumentMains,$performer(%_currentInstrumentRegex%,	),	)
        $foreach($unique(%_currentInstrumentMains%),
          $set(_performer,%_loop_value%)

          $noop(Standardize the musician names here, since it's not really possible to work on the performer names elsewhere)

          $noop(Undo select fancy punctuation)
          $set(_performer,$replace($get(_performer),‐,-))
          $set(_performer,$replace($get(_performer),“,"))
          $set(_performer,$replace($get(_performer),”,"))
          $set(_performer,$replace($get(_performer),’,'))
  
          $noop(Remove character from the vocal in CV credited names)
          $if($rsearch(%_performer%,[(\\\(][CcCc][\\..]{0\,1}[VvVv][:\\.:.\\s]),
            $set(_performer,$rreplace(%_performer%,\(.*\)\\s*\([(\\\(]\)\([CcCc][\\..]{0\,1}[VvVv]\)\([:\\.:.]\)\\s*\(.*\)\([)\\\)]\),\\5))
          )
$noop(
          $if($or($find(%_performer%,\(CV:),$find(%_performer%,\(CV.)),
            $set(_performer,$rreplace(%_performer%,\(.*\)\\\(CV[.:]\(.*\)\\\),\\2))
          )
      
          $if($or($find(%_performer%,\(cv:),$find(%_performer%,\(cv.)),
            $set(_performer,$rreplace(%_performer%,\(.*\)\\\(cv[.:]\(.*\)\\\),\\2))
          )
)

          $noop(Remove character from the vocal in Geneon-style starring credited names)
          $if($find(%_performer%, starring ),
            $set(_performer,$rreplace(%_performer%,\(.*\) starring \(.*\),\\2))
          )
          $noop(Remove BEMANI Sound Team)
          $if($find(%_performer%,BEMANI Sound Team),
            $set(_performer,$rreplace(%_performer%,BEMANI Sound Team ["“”]\(.*\)["“”],\\1))
          )
          $noop(Remove Konami Amusement)
          $if($find(%_performer%,Konami Amusement),
            $set(_performer,$rreplace(%_performer%,Konami Amusement \\\(\(.*\)\\\),\\1))
          )
          $noop(Remove Konami Digital Entertainment)
          $if($find(%_performer%,Konami Digital Entertainment),
            $set(_performer,$rreplace(%_performer%,Konami Digital Entertainment \\\(\(.*\)\\\),\\1))
          )

          $copymerge($get(_temp_currentCustomPerformerField),_performer)
        )$noop(Close foreach performer in this performer prefix)
      )$noop(Close foreach performer prefix)

      $noop(Merge conflicts - remove local values not found in the server; add server values not found in local)
      $set(_temp_ordered_currentCustomPerformerValues,)
      $foreach($get(%_currentCustomPerformerField%),
        $set(_oldPerformerValue,%_loop_value%)
        $set(_foundOldPerformerValue,0)
        $foreach($unique($get(%_temp_currentCustomPerformerField%)),
          $if($eq(%_loop_value%,%_oldPerformerValue%),$set(_foundOldPerformerValue,1),)
        )
        $if($eq(%_foundOldPerformerValue%,1),$copymerge(_temp_ordered_currentCustomPerformerValues,_oldPerformerValue),)
      )

      $if(%_currentCustomPerformerField%,$delete(%_currentCustomPerformerField%))
      $noop(Add old values that I may have manually ordered)
      $copymerge(%_currentCustomPerformerField%,_temp_ordered_currentCustomPerformerValues)
      $noop(Add new values not found in my local tag at the end)
      $copymerge(%_currentCustomPerformerField%,%_temp_currentCustomPerformerField%)
$noop(
      $if(%_temp_currentCustomPerformerField%,$delete(%_temp_currentCustomPerformerField%))
)
      $copymerge(_temporaryPerformerFields,_temp_currentCustomPerformerField)
      $if(%_temp_ordered_currentCustomPerformerValues%,$unset(%_temp_ordered_currentCustomPerformerValues%))

      $noop(keep list of instruments so the tags can be scripted)
      $copymerge(_standardizedInstruments,_standardizedInstrument)
    )
  )

  $set(_skipInstrument,)
)$noop(Close foreach _instruments)

$noop(Delete temporary fields that leaked out from internal variables)
$foreach(%_temporaryPerformerFields%,
  $delete(%_loop_value%)
)
$noop(
$if(%_temporaryPerformerFields%,$delete(_temporaryPerformerFields))
)

$noop(Delete any local performer fields that the server doesn't know about following name standardization)
$foreach($unique($get(%_instrumentsFieldName%)),
  $set(_currentCustomPerformerField,performer %_loop_value%)
  $noop(Picard is case sensitive, so MP3 TXXX tags must be manually handled - Picard apparently reads ALLCAPS m4a tags as lower case...)
  $if($eq_any($upper(%_extension%),MP3),$set(_currentCustomPerformerField,$upper(%_currentCustomPerformerField%)))

  $if($find(%_standardizedInstruments%,%_loop_value%),,$delete(%_currentCustomPerformerField%))
)

$noop(Save instruments, removing any local instruments that MusicBrainz doesn't know about)
$delete(%_instrumentsFieldName%)
$foreach($unique(%_standardizedInstruments%),
  $set(_standardizedInstrument,%_loop_value%)
  $copymerge(%_instrumentsFieldName%,_standardizedInstrument)

  $noop(Flatten M4A performer tags: Mutagen writes multi-value tags that can't be read correctly by foobar2000, Mp3tag, etc.)
  $if($eq($upper(%_extension%),M4A),
    $noop(Set custom field's name)
    $set(_currentCustomPerformerField,performer %_standardizedInstrument%)
    $set(%_currentCustomPerformerField%,$join($get(%_currentCustomPerformerField%),; ))
  )
)
$noop(Flatten M4A instruments tag: Mutagen writes multi-value tags that can't be read correctly by foobar2000, Mp3tag, etc.)
$if($eq($upper(%_extension%),M4A),
  $if($gt($lenmulti(%instruments%),0),
    $set(count_instruments,$lenmulti(%instruments%))
  )
  $set(instruments,$join(%instruments%,; ))
)

$unset(performer:*)

$noop(I like to indicate whether these are track-level, release-level, or 'reduction by ear' credits. You need to manually fill this in.)
$set(_instruments_precision,$get(%_instrumentsPrecisionField%))
$if($and($gt($lenmulti(%_instruments%),0),$eq(0,$len(%_instruments_precision%))),
$set(%_instrumentsPrecisionField%,?)
)