In 2005 musixdoc.pdf said:

Another question is: can I write an orchestral score and extract the separate scores for individual instruments?

Since T.108, the answer is nearly 99%

I gave up trying to understand this chapter and I wrote my own program. It splits the \notes line into smaller sections between the "&". It tries to guess the right \NOTes or \notes for each section according to the note durations it finds there.

It is certainly imperfect but I would be happy to try it on a working MusiXTeX score. See the limits in my text file.

Bye,

Jean-Pierre Coulon
*  Extraction des parties s�par�es d'un  "conducteur" MusiXTeX
      implicit none
      integer longueur, indexpourc, ifichier, ipointeur, lgrsource
      integer indexet, noinstru, iligne, nbinstru
      integer isigneet, icenterp, iinstrpause
      integer iasucrer, nbasucrer
      character*1 champnoinstru
      character*4 debligne
      character*20 motasucrer(8) 
      character*40 nomsource
      character*10 newnotes(11:23), newn, actuellenotes
      character*30 nominput, nomoutput
      character*200 ligne
      character*1000 bigligne, newbout
      logical asucrer

      data nbasucrer/8/
      data motasucrer/'alaligne', 'alapage', 'linegoal', 'interins',
     + 'mgfa', 'eject', 'smallmusicsize', 'afterruleskip'/

      print *,' Nom de fichier "conducteur" .TEX ?'
      read *, nomsource
      ipointeur = longueur(nomsource)
      nominput = '\partoche\'//nomsource(1:ipointeur)//'.TEX'
      call trouvenb(nbinstru, nominput)

      open (unit=10, file=nominput, status='old')
      if (longueur(nomsource).eq.8) then
        lgrsource = 7   !   perd 8e caractere
      else
        lgrsource = longueur(nomsource)   ! ajoute 1 car pour no
      endif
      print *, 'coucou'
      do ifichier = 11, 11+nbinstru-1
        write (champnoinstru,'(z1)') ifichier-10
        nomoutput = '\partoche\'//
     +  nomsource(1:lgrsource)//champnoinstru//'.tex'
        call ouvrefichier(ifichier, nomoutput)
      enddo      
      iligne = 0
      do 
        read (10, '(a)', end=1000) ligne
        asucrer = .false.
        do iasucrer = 1, nbasucrer
          if (index(ligne, motasucrer(iasucrer)
     +     (1:longueur(motasucrer(iasucrer)))).ne.0) asucrer = .true.
        enddo
        debligne = ligne(1:4)
        if (index('\NOT\NOt\Not\not\zno', debligne).eq.0) then
          if (index(ligne,'instrumentnumber').ne.0) then
            do ifichier = 11, 11+nbinstru-1
              write(ifichier,'(a)') '\instrumentnumber1'
              write(ifichier,'(a)') '\nostartrule'
            enddo
          else if (index('\setclef\setname\setsign\setstaf',
     +    ligne(1:8)).ge.1) then        ! ligne specifique pour 1 instrum
            call getnoinstru(ligne, noinstru)
            write (10+noinstru,'(a)') ligne(1:longueur(ligne))
          else if (asucrer) then 
          else if (index(ligne,'\def\atnextbar{\znotes').gt.0) then! cas des 
\centerpause
            iinstrpause = 1
            do while (index(ligne,'\centerpause').gt.0)
              do while ((index(ligne,'&').gt.0).and.
     1        (index(ligne,'&').lt.index(ligne,'\centerpause')))
*                                     comptage des & avant \centerpause
                isigneet = index(ligne,'&')
                iinstrpause = iinstrpause + 1
                ligne(1:isigneet) = ' '
              enddo
              write (10+iinstrpause, '(a)') '\notes\sk\pause\sk\en'

              icenterp = index(ligne,'\centerpause')
              ligne(1:icenterp+11) = ' '
            enddo
          else
            do ifichier = 11, 11+nbinstru-1  !  lignes communes
              write(ifichier,'(a)') ligne(1:longueur(ligne))
            enddo
          endif
        else  !     lignes  \NOtes etc.
          indexpourc = index(ligne, '%')
          if (indexpourc.eq.0) then
            bigligne = ligne
          else
            bigligne = ligne(1:indexpourc-1)
          endif
          do while (index(ligne,'\en').eq.0)  !   recollage en une ligne 
            read (10, '(a)', end=1000) ligne
            indexpourc = index(ligne, '%')
            if (indexpourc.eq.0) then
              bigligne = bigligne(1:longueur(bigligne))//ligne
            else
              bigligne = bigligne(1:longueur(bigligne))//
     +        ligne(1:indexpourc-1)
            endif
          enddo
          ifichier = 11
*  recherche du champ \Notes actuel :
          ipointeur = 2
          do while (index('\|&', bigligne(ipointeur:ipointeur)).eq.0)
            ipointeur = ipointeur + 1
          enddo
          actuellenotes = bigligne(1:ipointeur-1)
          indexet = index(bigligne,'&')

          do while (indexet.ne.0)
            newnotes(ifichier) = actuellenotes  ! au cas o� ne changerait pas
            newbout = bigligne(ipointeur:indexet-1)
            if (longueur(newbout).ne.0) then
              if (actuellenotes(1:7).ne.'\znotes') then 
                call cherchenotes(newbout, newnotes(ifichier))
                newn = newnotes(ifichier)
              else
                newn = '\znotes'
              endif
              write(ifichier, '(a)') newn(1:longueur(newn))//
     +         newbout(1:longueur(newbout))//'\en'
            endif
            ipointeur = indexet + 1
            bigligne(1:ipointeur-1) = ' '
            ifichier = ifichier + 1
            indexet = index(bigligne,'&')
          enddo   !   reste le dernier instrument � faire

          newbout = bigligne(ipointeur:longueur(bigligne))
          if (actuellenotes(1:7).ne.'\znotes') then
            call cherchenotes(newbout, newnotes(ifichier))
            newn = newnotes(ifichier)
          else
            newn = '\znotes'
          endif
          write(ifichier, '(a)') newn(1:longueur(newn))//
     +    bigligne(ipointeur:longueur(bigligne)) 
        endif
        iligne = iligne + 1
      enddo
1000  stop
      close (unit=11)
      end

* remplacement de \NOtes, etc. selon valeurs notes
      subroutine  cherchenotes(pacson, newnotes)
      implicit none
      character*(*) pacson, newnotes
      logical contextetrio

      contextetrio = .false.

      if ((index(pacson,'triolet').gt.0).or.
     + (index(pacson,'xtuplet6').gt.0)) contextetrio = .true.

      if ((index(pacson,'\wh').gt.0).or.(index(pacson,'\pause').gt.0))
     +  newnotes = '\NOTEs'

      if ((index(pacson,'\hu').gt.0).or.(index(pacson,'\hl').gt.0)
     + .or.(index(pacson,'\ha').gt.0).or.
     1 (index(pacson,'\hpause').gt.0)) newnotes = '\NOTes'

      if ((index(pacson,'\qu').gt.0).or.(index(pacson,'\ql').gt.0)
     + .or.(index(pacson,'\qp').gt.0)
     1 .or.(index(pacson,'\qa').gt.0)) newnotes = '\NOtes'

      if ((index(pacson,'\qup').gt.0).or.(index(pacson,'\qlp').gt.0))
     1 newnotes = '\NOtesp'

      if ((index(pacson,'\cu').gt.0).or.(index(pacson,'\cl').gt.0)
     + .or.(index(pacson,'\ds').gt.0).or.(index(pacson,'\ib').gt.0)
     1 .or.(index(pacson,'\ca').gt.0)) then
        if (contextetrio) then
          newnotes = '\notesp'
        else
          newnotes = '\Notes'
        endif
      endif

      if ((index(pacson,'\cup').gt.0).or.(index(pacson,'\clp').gt.0)
     +  .or.(index(pacson,'\qbp').gt.0)) newnotes = '\Notesp'

      if ((index(pacson,'\ccu').gt.0).or.(index(pacson,'\ccl').gt.0)
     + .or.(index(pacson,'\qs').gt.0).or.(index(pacson,'\ibb').gt.0)
     1 .or.(index(pacson,'\nbb').gt.0)) then
          if (contextetrio) then           
           newnotes = '\notess'
         else
           newnotes = '\notes'
         endif
      endif

      if ((index(pacson,'\ccup').gt.0).or.(index(pacson,'\cclp').gt.0)
     1 .or.((index(pacson,'\ibb').gt.0).and.
     2 (index(pacson,'\qbp').gt.0)))
     3  newnotes = '\notesp'

      if ((index(pacson,'\cccu').gt.0).or.(index(pacson,'\cccl').gt.0)
     + .or.(index(pacson,'\ibbb').gt.0).or.(index(pacson,'\nbbb').gt.0))
     2  newnotes = '\notess'

      return    !   si rien trouv� on laisse newnotes tel quel(tqb, tqh, etc)
      end

* recherche nb instruments dans tout le fichier
      subroutine trouvenb(nbinstru, nominput)
      integer nbinstru
      character*2 champinstru
      character*(*) nominput
      character*200 ligne

      open (unit=10, file=nominput, status='old')
      nbinstru = 0
      do while(nbinstru.eq.0)
        read (10, '(a)', end=2000) ligne
        if (index(ligne,'\instrumentnumber').ne.0) then
          if (index(ligne,'{').eq.0) then
            champinstru = ligne(18:18)
          else
            if (index(ligne,'{').eq.20) then 
              champinstru = ligne(19:19)!   cas nbinstru entre {}
            else
              champinstru = ligne(19:20)!   cas {10}, {11}, {12}
           endif   
          endif
          read (champinstru, *, err=2100) nbinstru
        endif
      enddo
2000  close (unit=10)
      print *, 'nbinstru = ', nbinstru
      return
2100  print *, 'Nb instruments illisible !'
      print *, ligne
      stop
      end

* recherche no instru dans lignes \set???   et forcage no instru � 1

      subroutine getnoinstru(ligne, noinstru)
      implicit none
      integer noinstru, pointeurferm 
      character*2 champinstru
      character*(*) ligne
      character*70 oldligne

      oldligne = ligne
      pointeurferm = index(ligne,'}')
      if (index(ligne,'\setstaffs').eq.0) then 
        if (ligne(9:9).ne.'{') then
          champinstru = ligne(9:9) 
          ligne(9:9) = '1'
        else
          champinstru = ligne(10:pointeurferm-1) 
          ligne(10:pointeurferm-1) = '1'
        endif
      else        !   cas \setclef, \setname, \setsign
        if (ligne(11:11).ne.'{') then
          champinstru = ligne(11:11)!   
          ligne(11:11) = '1'
        else
          champinstru = ligne(12:pointeurferm-1)
          ligne(12:pointeurferm-1) = '1'
        endif   
      endif
      read (champinstru, *, err=1100) noinstru
      return
1100  print *, 'No instrument illisible !'
      print *, oldligne
      stop
      end

      include 'ouvrefile.inc'
      include 'longueur.inc'
Avoid using \sk. commands, e.g. don't say:
\NOtes\hu C\sk\hu D&\qu{cdef}\en
but:
\NOtes\hu C&\qu{cd}\en
\NOtes\hu D&\qu{ef}\en
This because the program will automatically associate \NOTes with \hu. 

Stick \Notes and \set{clef, name, sign, staffs} commands left. Do not
put several \set{something} commands on the same line. Otherwise they
won't be seen. 

If you need notes closer to each other than provided by \notes, do not
create your own command similar to \notes, but say e.g. \multnoteskip{.7}
instead.

Do not create sophisticated macros, especially those involving commands
quoted above.

The parts produced may still require some work, e.g.:
- slurs and hairpins across bars,
- consecutive rest measures may need to be rewritten in \PAuse or \PAUSe,
with the corresponding number, and \barno needs be adjusted. 
- cue notes or the like. 



-------------------------------
[email protected] mailing list
If you want to unsubscribe or look at the archives, go to 
http://tug.org/mailman/listinfo/tex-music

Reply via email to