1 ;;; transcribe.el --- Package for audio transcriptions
3 ;; Copyright 2014-2015 Free Software Foundation, Inc.
5 ;; Author: David Gonzalez Gandara <dggandara@member.fsf.org>
8 ;; This program is free software: you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation, either version 3 of the License, or
11 ;; (at your option) any later version.
13 ;; This program is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;; GNU General Public License for more details.
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
24 ;; -----------------------------
25 ;; This module works without any requires, but in order to use the audio
26 ;; functions, you need to install the emacs package "emms", by Joe Drew,
27 ;; and the external program "mpg321", by Jorgen Schafer and Ulrik Jensen,
28 ;; both under GPL licenses.
31 ;; -------------------------
32 ;; Transcribe is a tool to make audio transcriptions. It allows the
33 ;; transcriber to control the audio easily while typing, as well as
34 ;; automate the insertion of xml tags, in case the transcription protocol
36 ;; The analyse function will search for a specific structure
37 ;; of episodes that can be automatically added with the macro NewEpisode.
38 ;; The function expects the speech acts to be transcribed inside a turn xml
39 ;; tag with the identifier of the speaker with optional move attribute.
40 ;; Each speech act is spected inside a <l1> or <l2> tag, depending
41 ;; on the language used by the person. The attributes expected are the
42 ;; number of clauses that form the utterance, the number of errors the
43 ;; transcriber observes, and the function of the speech act. The parser will
44 ;; even if some attributes are missing.
48 ;; ------------------------------
49 ;; C-x C-p ------> Play audio file. You will be prompted for the name
50 ;; of the file. The recommended format is mp2.
51 ;; <f5> ---------> Pause or play audio.
52 ;; C-x <right> --> seek audio 10 seconds forward.
53 ;; C-x <left> --->seek audio 10 seconds backward.
54 ;; <f8> ---------> seek interactively: positive seconds go forward and
55 ;; negative seconds go backward
57 ;; XML TAGGING COMMANDS
58 ;; --------------------------------------------------
59 ;; C-x C-n --> Create new episode structure. This is useful in case your
60 ;; xml file structure requires it. You can customize the text
61 ;; inserted manipulating the realted function.
62 ;; <f2> -----> Interactively insert a function attribute in a speech act
64 ;; <f3> -----> Interactively insert a move attribute in a turn (person) tag
65 ;; <f4> -----> Interactively insert an attribute (any kind)
66 ;; <f6> -----> Interactively insert new tag. You will be prompted for the
67 ;; content of the tag. The starting tag and the end tag will be
68 ;; inserted automatically and the cursor placed in the proper
73 ;; SPECIFIC COMMANDS I USE, THAT YOU MAY FIND USEFUL
74 ;; ------------------------------------------------
75 ;; C-x C-a ------> Analyses the text for measurments of performance.
76 ;; <f11> --------> Customised tag 1. Edit the function to adapt to your needs.
77 ;; <f12> --------> Customised tag 2. Edit the function to adapt to your needs.
78 ;; <f7> ---------> Break tag. This command "breaks" a tag in two, that is
79 ;; it inserts an ending tag and then a starting tag.
80 ;; <f4> ---------> Insert atributes. This function insert custom xml attributes.
81 ;; Edit the function to suit you needs.
85 (if t (require 'emms-setup))
86 ;(require 'emms-player-mpd)
87 ;(setq emms-player-mpd-server-name "localhost")
88 ;(setq emms-player-mpd-server-port "6600")
91 (emms-default-players)
92 (if t (require 'emms-player-mpg321-remote))
93 (defvar emms-player-list)
94 (push 'emms-player-mpg321-remote emms-player-list)
96 (if t (require 'emms-mode-line))
98 (if t (require 'emms-playing-time))
101 (defvar transcribe-function-list '("initiating" "responding" "control" "expresive" "interpersonal"))
102 (defvar transcribe-move-list '("initiation" "response" "follow-up"))
103 (defvar transcribe-attribute-list (append '("clauses" "errors") transcribe-function-list transcribe-move-list))
104 ;(append transcribe-attribute-list transcribe-function-list transcribe-move-list)
106 (defun transcribe-analyze-episode (episode person)
107 "This calls the external python package analyze_episodes2.py. The new
108 function transcribe-analyze implements its role now."
109 (interactive "sepisode: \nsperson:")
110 (shell-command (concat (expand-file-name "analyze_episodes2.py")
111 " -e " episode " -p " person " -i " buffer-file-name )))
113 (defun transcribe-analyze (episodenumber personid)
114 "Extract from a given episode and person the number of asunits per
115 second produced, and the number of clauses per asunits, for L2 and L1."
116 (interactive "sepisodenumber: \nspersonid:")
117 (let* ((interventionsl2 '())
118 (interventionsl1 '())
119 (xml (xml-parse-region (point-min) (point-max)))
121 (episodes (xml-get-children results 'episode))
132 (dolist (episode episodes)
133 (let*((numbernode (xml-get-children episode 'number)))
135 (setq number (nth 2 (car numbernode)))
136 (when (equal episodenumber number)
137 (let* ((durationnode (xml-get-children episode 'duration))
138 (transcription (xml-get-children episode 'transcription)))
140 (setq duration (nth 2 (car durationnode)))
141 (dolist (turn transcription)
142 (let* ((interventionnode (xml-get-children turn
145 (dolist (intervention interventionnode)
146 (let* ((l2node (xml-get-children intervention 'l2))
147 (l1node (xml-get-children intervention 'l1)))
149 (dolist (l2turn l2node)
150 (let* ((l2 (nth 2 l2turn))
151 (clausesl2node (nth 1 l2turn))
152 (clausesl2nodeinc (cdr (car clausesl2node))))
154 (when (not (equal clausesl2node nil))
155 (setq clausesl2 (+ clausesl2 (string-to-number
157 (when (not (equal l2 nil))
158 (add-to-list 'interventionsl2 l2)
159 (setq asunitsl2 (1+ asunitsl2)))))
160 (dolist (l1turn l1node)
161 (let*((l1 (nth 2 l1turn))
162 (clausesl1node (nth 1 l1turn))
163 (clausesl1nodeinc (cdr (car clausesl1node))))
165 (when (not (equal clausesl1node nil))
166 (setq clausesl1 (+ clausesl1 (string-to-number
168 (when (not (equal l1 nil))
169 (add-to-list 'interventionsl1 l1)
170 (setq asunitsl1 (1+ asunitsl1)))))))))))))
171 (reverse interventionsl2)
172 (reverse interventionsl1)
173 ;(print interventions) ;uncomment to display all the interventions on screen
174 (let((asunitspersecondl2 (/ asunitsl2 (string-to-number duration)))
175 (clausesperasunitl2 (/ clausesl2 asunitsl2))
176 (asunitspersecondl1 (/ asunitsl1 (string-to-number duration)))
177 (clausesperasunitl1 (/ clausesl1 asunitsl1)))
179 (princ (format "episode: %s, duration: %s, person: %s\n" episodenumber duration personid))
180 (princ (format "L2(Asunits/second): %s, L2(clauses/Asunit): %s, L1(Asunits/second): %s"
181 asunitspersecondl2 clausesperasunitl2 asunitspersecondl1)))))
183 (defun transcribe-define-xml-tag (xmltag)
184 "This function allows the automatic insetion of a xml tag and places the cursor."
185 (interactive "stag:")
186 (insert (format "<%s></%s>" xmltag xmltag))
188 (backward-char (string-width xmltag)))
190 (defun transcribe-add-attribute (att val)
191 "Adds a xml attribute at cursor with the name and value specified (autocompletion possible)"
192 (interactive (list(completing-read "attibute name:" transcribe-attribute-list)(read-string "value:")))
193 (insert (format "%s=\"%s\"" att val)))
195 (defun transcribe-add-attribute-function (val)
196 "Adds the xml attribute 'function' at cursor with the name specified (autocompletion possible)"
197 (interactive (list(completing-read "function name:" transcribe-function-list)))
198 (insert (format "function=\"%s\"" val)))
200 (defun transcribe-add-attribute-move (val)
201 "Adds the xml attribute 'move' at cursor with the name specified (autocompletion possible"
202 (interactive (list(completing-read "move name:" transcribe-move-list)))
203 (insert (format "move=\"%s\"" val)))
205 (defun transcribe-xml-tag-l1 ()
206 "Inserts a l1 tag and places the cursor"
212 (defun transcribe-xml-tag-l2 ()
213 "Inserts a l2 tag and places the cursor"
215 (insert "<l2 clauses=\"1\" errors=\"0\"></l2>")
219 (fset 'transcribe-xml-tag-l2-break "</l2><l2 clauses=\"1\" errors=\"0\">")
220 ;inserts a break inside a l2 tag
222 (defun transcribe-display-audio-info ()
224 (emms-player-mpg321-remote-proc)
225 (shell-command "/usr/bin/mpg321 -R - &"))
229 "<episode>\n<number>DATE-NUMBER</number>\n<duration></duration>\n<comment></comment>\n<subject>Subject (level)</subject>\n<task>\n\t<role>low or high</role>\n<context>low or high</context>\n<demand>low or high</demand>\r</task>\n<auxiliar>Yes/no</auxiliar>\n<transcription>\n</transcription>\n</episode>");Inserts a new episode structure
232 (define-minor-mode transcribe-mode
233 "Toggle transcribe-mode"
236 '(([?\C-x ?\C-p] . emms-play-file)
237 ([?\C-x ?\C-a] . transcribe-analyze)
238 ([?\C-x ?\C-n] . NewEpisode)
239 ([?\C-x down] . emms-stop)
240 ([?\C-x right] . emms-seek-forward)
241 ([?\C-x left] . emms-seek-backward)
242 ([f2] . transcribe-add-attribute-function)
243 ([f3] . transcribe-add-attribute-move)
244 ([f4] . transcribe-add-atribute)
246 ([f6] . transcribe-define-xml-tag)
247 ([f7] . transcribe-xml-tag-l2-break)
250 ([f11] . transcribe-xml-tag-l1)
251 ([f12] . transcribe-xml-tag-l2))
254 (provide 'transcribe)
256 ;;; transcribe.el ends here