root/experimental/components/rc2007_gui/WorkModules.py @ 5524

Revision 5524, 12.7 KB (checked in by jgaeddert, 6 years ago)

changing metadata initialization method to comply with r5523

  • Property svn:eol-style set to native
Line 
1
2'''
3/****************************************************************************
4
5Copyright 2007 Virginia Polytechnic Institute and State University
6
7This file is part of the OSSIE USRP_Commander_GUI.
8
9OSSIE USRP_Commander_GUI is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2 of the License, or
12(at your option) any later version.
13
14OSSIE USRP_Commander_GUI is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with OSSIE USRP_Commander_GUI; if not, write to the Free Software
21Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
23****************************************************************************/
24
25'''
26
27#!/usr/bin/env python
28import threading
29import standardInterfaces__POA
30import standardInterfaces as SI
31
32import math   # only needed for sine wave that is generated to test sound out
33import random
34
35import time
36import ossaudiodev
37import struct   # for audio
38import copy
39
40import cvsd     # this is in my rc2007_gui package directory
41
42import pprint
43
44def pack_audio(v, num_channels=1):
45    '''packs a list of signed shorts into a string which can be read by
46    the audio device'''
47    s = ''
48    for i in v:
49        s += struct.pack('h', i)
50        if num_channels==2:
51            s+= '\0\0'
52    return s
53
54def unpack_audio(s, num_channels=1):
55    '''unpacks a string into a vector'''
56    v = []
57    if num_channels==2:
58        d = 4
59    else:
60        d = 2
61
62    for i in range(0,len(s),d):
63        v.append( struct.unpack('h', s[i:(i+2)])[0] )
64    return v
65
66def energy(x):
67    e = 0
68    for i in x:
69        e += i*i
70    return math.sqrt(e/len(x))
71
72# global sound card variables
73audio_sampling_frequency = 16000
74audio_channels = 1
75audio_buffer_length = 1024
76
77def CreateMetadataObject():
78    modulation_scheme = SI.ModulationScheme(SI.ModulationScheme.PSK, 2)
79
80    packet_id = 0
81    sampling_frequency = 0.0
82    carrier_frequency = 0.0
83    signal_bandwidth = 0.0
84    signal_strength = 0.0
85    eom = True
86    src_id = 0
87    dst_id = 0
88    app_id = 0
89    port_id = 0
90    packet_type = 0
91    default_metadata = SI.MetaData(modulation_scheme,
92                                   packet_id,
93                                   sampling_frequency,
94                                   carrier_frequency,
95                                   signal_bandwidth,
96                                   signal_strength,
97                                   eom,
98                                   src_id,
99                                   dst_id,
100                                   app_id,
101                                   port_id,
102                                   packet_type)
103    return default_metadata
104
105
106class txWorkClass:
107
108    def __init__(self, rc2007_gui_ref):
109        '''Initialization.  Sets a reference to parent. 
110        Initializes the buffer.  Starts the Process data
111        thread, which waits for data to be added to the buffer'''
112
113        self.rc2007_gui_ref = rc2007_gui_ref
114   
115        # open the capture device and set properties
116        Fs = audio_sampling_frequency   # sampling frequency
117        self.num_channels = audio_channels
118
119        # open the playback device and set properties
120        self.mic_driver = ossaudiodev.open('r')
121        self.mic_driver.setfmt(ossaudiodev.AFMT_S16_LE)
122        self.mic_driver.channels(self.num_channels)
123        self.mic_driver.speed(Fs)
124
125
126        self.buf_len = audio_buffer_length
127
128        self.voice_data_queue = []
129        self.voice_data_queue_lock = threading.Lock()
130        self.voice_data_signal = threading.Event()
131        self.is_running = True
132
133        # create meta data objects for audio and text
134        self.audio_metadata = CreateMetadataObject()
135        self.text_metadata = CreateMetadataObject()
136
137        self.my_encoder = cvsd.encoder()
138        self.my_decoder = cvsd.decoder()
139        self.CVSD_e_thread = threading.Thread(target=self.CVSD_encode)
140        self.CVSD_e_thread.start()
141       
142        self.process_thread = threading.Thread(target=self.Process)
143        self.process_thread.start()
144   
145    def __del__(self):
146        '''Destructor'''
147        self.mic_driver.close()
148        self.speaker_driver.close()
149        pass
150   
151    def CVSD_encode(self):
152        # get voice from mic
153        while self.is_running:
154            raw_voice = self.mic_driver.read(self.buf_len)
155            voice_data = unpack_audio(raw_voice, self.num_channels)
156            self.AddVoiceData(voice_data)
157
158            # For now, I need to sleep for a little bit so that
159            # this thread does not take up all of my processor.
160            # This will effectively slow my data rate
161            #time.sleep(.1)
162
163    def AddVoiceData(self, data):
164        '''Generally called by parent.  Adds data to a buffer.
165        The Process() method will wait for this buffer to be set.
166        '''
167        self.voice_data_queue_lock.acquire()
168        self.voice_data_queue.insert(0, data)
169        self.voice_data_queue_lock.release()
170        self.voice_data_signal.set()
171   
172    def SendTextData(self,text):
173        # TODO: pack/depack
174        # tmp: False for text
175        # configure meta data here
176        self.text_metadata.eom = False
177        self.text_metadata.packet_id += 1
178        #print "text " + str(self.text_metadata.packet_id) + "  " + text
179        self.rc2007_gui_ref.to_radio_port_servant.send_data(
180                text,
181                copy.copy(self.text_metadata))
182   
183    def Release(self):
184        self.is_running = False
185        self.voice_data_signal.set()
186       
187    def Process(self):
188        while self.is_running:
189            self.voice_data_signal.wait()  # wait for data to be aded to the
190                                           # buffer in self.AddVoiceData()
191            while len(self.voice_data_queue) > 0:
192                # get the data from the buffer:
193                self.voice_data_queue_lock.acquire()
194                data = self.voice_data_queue.pop()
195                self.voice_data_queue_lock.release()
196               
197                # forwarding voice data:
198                if self.rc2007_gui_ref.talk_flag:
199                    # encode audio data using CVSD codec
200                    data_int = self.my_encoder.Encode(data)
201                    # pack integers into string
202                    # NOTE: this does NOT mean that an integer zero is
203                    #   converted into an ASCII '0' character, but rather
204                    #   the '\x00' character
205                    data = ''
206                    for b in data_int:
207                        data += struct.pack('B', b);
208                    # tmp: true for voice
209                    # configure meta data here
210                    self.audio_metadata.eom = True
211                    self.audio_metadata.packet_id += 1
212
213                    #print ">"*4 + " audio enc " + str(self.audio_metadata.packet_id) + \
214                    #      "  " + str(data_int[0:10])
215       
216                    if self.rc2007_gui_ref.to_radio_port_active:
217                        #print "audio length: " + str(len(data))
218                        self.rc2007_gui_ref.to_radio_port_servant.send_data(
219                                data,
220                                copy.copy(self.audio_metadata))
221
222            self.voice_data_signal.clear()  # done reading the buffer
223               
224
225
226class rxWorkClass:
227
228    def __init__(self, rc2007_gui_ref):
229        '''Initialization.  Sets a reference to parent. 
230        Initializes the buffer.  Starts the Process data
231        thread, which waits for data to be added to the buffer'''
232
233        self.rc2007_gui_ref = rc2007_gui_ref
234   
235        # new method:
236        self.num_channels = audio_channels
237        Fs = audio_sampling_frequency
238        self.speaker_driver = ossaudiodev.open('w')
239        self.speaker_driver.setfmt(ossaudiodev.AFMT_S16_LE)
240        self.speaker_driver.channels(self.num_channels)
241        self.speaker_driver.speed(Fs)
242
243        self.data_queue = []
244        self.data_queue_lock = threading.Lock()
245        self.data_signal = threading.Event()
246
247        self.is_running = True
248
249        # old method:
250        #self.channels = 2
251        #self._setup_sound()
252
253        self.my_decoder = cvsd.decoder()
254
255        self.process_thread = threading.Thread(target=self.Process)
256        self.process_thread.start()
257
258    def _setup_sound(self):
259        self.timing_diff = 1000
260        self.ossspeed = 100000
261        self.osschannels = 1
262        self.ossfmt = ossaudiodev.AFMT_S16_LE
263        self.CORBA_being_used = False
264
265        self.sound_driver = ossaudiodev.open('w')
266        self.osschannels = self.sound_driver.channels(2)
267        self.ossfmt = self.sound_driver.setfmt(ossaudiodev.AFMT_S16_LE)
268        self.ossspeed = self.sound_driver.speed(50000)
269        self.sound_driver.nonblock()
270   
271    def __del__(self):
272        '''Destructor'''
273        pass
274   
275    def AddMetaData(self, data, meta_data):
276        '''Generally called by parent.  Adds data to a buffer.
277        The Process() method will wait for this buffer to be set.
278        '''
279        self.data_queue_lock.acquire()
280        self.data_queue.insert(0, (data, meta_data) )
281        self.data_queue_lock.release()
282        self.data_signal.set()
283   
284    def CVSDDecode(self, data):
285        # data is real char
286        unpacked_audio = self.my_decoder.Decode(data)
287
288        # The old method
289        #self.playAudio(left_channel, right_channel)
290
291        # the new method
292        #print " output audio energy : " + str(int(energy(data)))
293        packed_audio = pack_audio(unpacked_audio, self.num_channels)
294        self.speaker_driver.writeall(packed_audio)       
295
296    def playAudio(self,Left_channel, Right_channel):
297            # play on speaker
298            my_string = ''
299            if Right_channel[0]==0:     # using the left channel
300                for y in range(0,len(Left_channel)):
301                    upper_val = Left_channel[y]/256
302                    lower_val = Left_channel[y] - (upper_val * 256)
303                    my_string += struct.pack('h', Left_channel[y])
304                    #my_string += struct.pack('B',lower_val)
305                    #my_string += struct.pack('b',upper_val)
306                    if self.channels == 2:
307                        my_string += '\0'
308                        my_string += '\0'
309                    else:
310                        my_string += struct.pack('h', Left_channel[y])
311                        #my_string += struct.pack('B',lower_val)
312                        #my_string += struct.pack('b',upper_val)
313            else:     # using the right channel
314                for y in range(0,len(Right_channel)):
315                    upper_val = Right_channel[y]/256
316                    lower_val = Right_channel[y] - (upper_val * 256)
317                    my_string += struct.pack('h', Right_channel[y])
318                    #my_string += struct.pack('B',lower_val)
319                    #my_string += struct.pack('b',upper_val)
320                    if self.channels == 2:
321                        my_string += '\0'
322                        my_string += '\0'
323                    else:
324                        my_string += struct.pack('h', Right_channel[y])
325                        #my_string += struct.pack('B',lower_val)
326                        #my_string += struct.pack('b',upper_val)
327            self.sound_driver.writeall(my_string)
328
329    def Release(self):
330        self.is_running = False
331        self.data_signal.set()
332       
333    def Process(self):
334        while self.is_running:
335
336            self.data_signal.wait()  # wait for data to be aded to the
337                                     # buffer in self.AddVoiceData()
338            while len(self.data_queue) > 0:
339                # get the data from the buffer:
340                self.data_queue_lock.acquire()
341                (data, metadata) = self.data_queue.pop()
342                self.data_queue_lock.release()
343       
344                # temp: if EOM is true data are voice, otherwise text
345                voice = metadata.eom
346                text = not voice
347
348                # TODO: look at the metadata and decide if it's voice or text       
349                # forwarding voice data:
350                if voice:
351                    # convert string to list of integers
352                    data_int = []
353                    for c in data:
354                        data_int.append( int(struct.unpack('B', c)[0]) )
355                    #print "<"*4 + " audio dec " + str(metadata.packet_id) + \
356                    #      "  " + str(data_int[0:10])
357
358                    self.CVSDDecode(data_int)
359
360                if text:
361                    self.rc2007_gui_ref.prnt_app.frame.DisplayText(data)
362
363            self.data_signal.clear()  # done reading the buffer
364
365
366
367
Note: See TracBrowser for help on using the browser.