Welcome, guest | Sign In | My Account | Store | Cart

For MacBook_Pro-Heads Only. Simple LF Audio Oscilloscope Using Standard Text Mode Python.

SimpleScope_OSX.py

Do you remember this upload from myself on 26-06-2011...

http://code.activestate.com/recipes/577771-simple-lf-audio-oscilloscope-using-standard-text-m/?in=user-4177147

Well here is an August 2012 vintage MacBook Pro 13 inch version of it for OSX 10.7.5...

This is proof of concept code for a kids level project I am doing for a MacBook Pro, 13 inch, OSX 10.7.5. A DEMO to show how to display a waveform using standard text mode Python. "pyaudio" must be installed for this to work. Levels are set using the standard audio mixers, (System Preferences -> Sound).

Just whistle a signal of say 300Hz to 3KHz, (normal voice spectrum), using say, the internal mic, and watch a waveform appear inside the X-Y graticule.

Read the code for more information.

$VER: SimpleScope_OSX.py_Version_0.00.10_(C)2012_B.Walker_G0LCU.

This code is GPL2, but, the hardware information is Public Domain.

(I am looking into including Windows and Linux variants too using pyaudio to access the sound system.)

Enjoy finding simple solutions to often very difficult problems.

Bazza, G0LCU...

Python, 181 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# SimpleScope_OSX.py
# A standard text mode Python Audio LF Oscilloscope DEMO for a MacBook Pro 13 inch.
# This is the basis for a sound card, almost realtime, AF Oscilloscope in development.
#
# Disclaimer:-
#
# You take this information and use it ENTIRELY at your own risk.
# I hold no responsibility for any errors either in this text or with your electronics capabilities...
#
# The reason I have given this hardware information away is/was because I needed an audio input for
# a simple MacBook Pro Python Audio-Oscilloscope I am developing for the MacBook Pro 13 inch model.
#
# BEST VIEWED IN PLAIN TEXT!
#
# Input/Output adaptor for the Apple MacBook Pro 13 inch only.
# (This MAY be good for the MBP Retina Versions too!)
#
# Mac_OS Version, OSX 10.7.5...
#
# Machine vintage:- August 2012.
#
# Common 3.5mm Mic/Ear socket cable for external MONO audio input, (and stereo audio output)...
#
# Plug required, (or similar)...
#
# http://www.ebay.co.uk/itm/3-5mm-Mini-Jack-Right-Angle-90-Degree-Solder-4-Pole-Male-Plug-Connector-/320770305756
#
# Resistor, 2K2, 1/8W, 10% tolerance...
# Resistor, 33 Ohms, 1W, 10% tolerance, 2 off...
# (Coloured wire as required...)
#
# This is the 4 pole 3.5mm plug wiring, for auto-switching of the Mic input to external...
#
# Pins.               Wiring.
# -----    TIP        -------
#  1 ---->  O  <----- Left Audio Output +ve.
#  2 ---->  H  <----- Right Audio Output +ve.
#  3 ---->  H  <----- Mono (Mic) Input, Active.
#  4 ---->  H  <----- Common To All Inputs And Outputs.
#          ---
#         |   |
#         |   |______
#         |__________|=========
#
# For the microphone auto-switching capability a 2K2 resistor must be connected across Pins 3 and 4, [Mono (Mic) Input, Active and Common]...
# Connect one 33 Ohm resistor between Pins 1 and 4 and the other 33 Ohm resistor between Pins 2 and 4...
#
# Test by plugging into the socket and check that the "System Preferences > Sound" switches over to external input and output.
# Be aware that it takes a few seconds to switch over, it is NOT instantaneous...
#
# You now have two audio outputs at low impedance and an analogue audio input at around 2K2 _impedance_.
#
# Do NOT drive the input with more than 100mV AC and do NOT connect to a DC _supply_ either.
#
# Do NOT load the audio outputs with less than 33 Ohm resistors.
#
# Do NOT assume that Common is connected to GND, Ground, of the computer, although it may well be.
#
# I am assuming that if you are capable of doing this that you are also capable of doing the subtle level tests, etc...
#
# (C)2012, B.Walker, G0LCU. The Cable assembly modifictaions are Public Domain, but the code is GPL2...
#
# Enjoy finding simple solutions to often very difficult problems... ;o)
#
# Tested on Python Versions 2.5.6, 2.6.7 and 2.7.1 with pyaudio installed.
#
# $VER: SimpleScope_OSX.py_Version_0.00.10_(C)2012_B.Walker_G0LCU.

# The imports required...
import os
import sys
import pyaudio

def main():
	# Set everything as global just for this DEMO; my choice... ;o)
	global ScopeScreen
	global ScopeWindow
	global plot
	global position
	global horiz
	global record
	global data
	global grab
	global n
	global dec_val

	# Allocate initial values.
	ScopeScreen="(C)2011, B.Walker, G0LCU."
	ScopeWindow="Simple LF Audio Oscilloscope."
	plot=0
	position=67
	horiz=0
	record=" "
	data=" "
	grab=255
	n=0
	dec_val=0

	while 1:
		# This is the basic Osilloscope graticule window for this DEMO.
		ScopeScreen="+-------+-------+-------+-------+-------+-------+-------+--------+\n"
		ScopeScreen=ScopeScreen+"|       |       |       |       +       |       |       |        |\n"
		ScopeScreen=ScopeScreen+"|       |       |       |       +       |       |       |        |\n"
		ScopeScreen=ScopeScreen+"|       |       |       |       +       |       |       |        |\n"
		ScopeScreen=ScopeScreen+"|       |       |       |       +       |       |       |        |\n"
		ScopeScreen=ScopeScreen+"+-------+-------+-------+-------+-------+-------+-------+--------+\n"
		ScopeScreen=ScopeScreen+"|       |       |       |       +       |       |       |        |\n"
		ScopeScreen=ScopeScreen+"|       |       |       |       +       |       |       |        |\n"
		ScopeScreen=ScopeScreen+"|       |       |       |       +       |       |       |        |\n"
		ScopeScreen=ScopeScreen+"+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++\n"
		ScopeScreen=ScopeScreen+"|       |       |       |       +       |       |       |        |\n"
		ScopeScreen=ScopeScreen+"|       |       |       |       +       |       |       |        |\n"
		ScopeScreen=ScopeScreen+"|       |       |       |       +       |       |       |        |\n"
		ScopeScreen=ScopeScreen+"+-------+-------+-------+-------+-------+-------+-------+--------+\n"
		ScopeScreen=ScopeScreen+"|       |       |       |       +       |       |       |        |\n"
		ScopeScreen=ScopeScreen+"|       |       |       |       +       |       |       |        |\n"
		ScopeScreen=ScopeScreen+"|       |       |       |       +       |       |       |        |\n"
		ScopeScreen=ScopeScreen+"+-------+-------+-------+-------+-------+-------+-------+--------+\n"

		# Save the this graticule window for further writing to.
		ScopeWindow=open("ScopeScreen.txt","wb+")
		ScopeWindow.write(ScopeScreen)
		ScopeWindow.close()

		# Access the sound system...
		# A modified version of the pyaudio demo code at:- http://people.csail.mit.edu/hubert/pyaudio/
		stream=pyaudio.PyAudio().open(format=pyaudio.paInt8,channels=1,rate=48000,input=True,frames_per_buffer=1024)
		all=[]
		for n in range(0,48000/1024*1,1):
			record=stream.read(1024)
			all.append(record)
		stream.close()
		pyaudio.PyAudio().terminate()
		record="".join(all)
		# Convert to unsigned data because paUInt8 does NOT work in Python on a MocBook Pro, 13 inch...
		# "struct.unpack" did not work as predicted so converted longhand; remember, this code is only
		# a proof of concept and may yet be done in 16 bit depth.
		data=""
		for n in range(0,len(record),1):
			dec_val=ord(record[n])
			if dec_val>=0 and dec_val<=127:
				dec_val=dec_val+128
				data=data+chr(dec_val)
			dec_val=ord(record[n])
			if dec_val>=128 and dec_val<=255:
				dec_val=dec_val-128
				data=data+chr(dec_val)

		# Now plot the graph...
		horiz=0
		ScopeWindow=open("ScopeScreen.txt","rb+")
		while horiz<=63:
			# Convert each part of the record string into decimal.
			grab=ord(data[horiz])
			# Now convert to 4 bit depth purely for text mode displays only.
			plot=int(grab/16)
			# Invert to suit the text display window.
			plot=15-plot
			# Don't allow an error.
			if plot<=0: plot=0
			if plot>=15: plot=15
			# Set up the horizontal position and plot.
			position=68+horiz+plot*67
			ScopeWindow.seek(position)
			ScopeWindow.write("o")
			horiz=horiz+1

		# Now get the whole ScopeWindow with the plotted points......
		ScopeWindow.seek(0)
		ScopeScreen=ScopeWindow.read(1206)
		ScopeWindow.close()
		# ......and print it to the terminal window.
		print os.system("clear"),chr(13),"  ",chr(13),
		print ScopeScreen
		print "Simple Audio Oscilloscope DEMO using pyaudio for OSX 10.7.5."
		print "Ctrl-C to quit..."

main()

# SimpleScope_OSX.py program end; release date:- 07-10-2012...
# Enjoy finding simple solutions to often very difficult problems.

This is for the BIG GUNS who think that they can read and understand how code works WITHOUT any relevent comments...

Just two ultra_simple changes to this code will alter the _sync_ point and/or timebase speeds. I will let the big guns do the changes and tell those who don't know what they have done via the comments section.

Release date:- 07-10-2012...

This method is being used for a program proper using the MacBook Pro 13 inch; a DC~20KHz AudioScope using the analogue mono microphone input... The AC component will probably be 8 bit depth, but I don't think I can get the DC component better than 6 bit depth.

A partially started front end using Tkinter is here:-

http://wisecracker.host22.com/public/Scope1.tiff

This is a GIF animation of an AMIGA project I did years ago and will try to emulate using Python, Tkinter and pyaudio:-

http://wisecracker.host22.com/public/SCOPE.GIF

Enjoy finding simple solutions to often very difficult problems.

Bazza, G0LCU...

1 comment

Barry Walker (author) 11 years, 5 months ago  # | flag

By kind permission.

Many thanks to Hubert Pham author of the pyaudio module for checking on OSX 10.8.x:-

""" Seems to work on my Mac (10.8) with Python 2.7, but only if I change the sampling rate down to 44100. At 48000, I guess the sound card fills up the audio buffer faster than the loop can read. Looks cool! """

Bazza, G0LCU...