USB MIDI Interface Driver

James Moxham

Member
Licensed User
Longtime User
Probably not. I'm still trying to work out what works and what does not. I have tried a USB pendrive, USB mouse, USB keyboard and USB to serial device. Of those, the pendrive and keyboard worked, and the mouse and serial device didn't.

It is partly about getting drivers working. There are many threads that talk about overwriting the entire android operating system in order to get a peripheral to work but I'm not all that keen on that solution.

This is an exercise in thinking outside the square. My android does not have bluetooth in the hardware but the support is there in the operating system software, so maybe maybe a bluetooth USB dongle might work. That might then interface to a bluetooth to serial device. And maybe you can get into midi that way?

I think the quickest path to midi might be the jetplayer and audiotrack APIs.

I wonder if it is worth getting Eclipse and Java and coding a few lines of java just to prove these APIs work on the hardware? Though I'd prefer to code in Basic!
 
Upvote 0

Bob Katayama

Member
Licensed User
Longtime User
Thanks for your input.
I am not going to give up yet. Maybe sending MIDI data directly via serial protocol may have to be the solution if an external driver cannot be used to generically interface with the serial hardware.

Bob
 
Upvote 0

James Moxham

Member
Licensed User
Longtime User
I am not going to give up yet

Me neither. I guess USB things have been around for so long that you just plug them in and expect them to work.

The idea I have is to send data out of the audio socket and emulate the waveforms of a serial data stream. I was thinking 1200 baud to start with, but no reason it could not be faster. eg Midi is 31.25khz. I see one of the methods in audiotrack is
B4X:
public int setPlaybackRate (int sampleRateInHz) 
Since: API Level 3 

Sets the playback sample rate for this track. This sets the sampling rate at which the audio data will be consumed and played back, not the original sampling rate of the content. Setting it to half the sample rate of the content will cause the playback to last twice as long, but will also result in a negative pitch shift. The valid sample rate range if from 1Hz to twice the value returned by getNativeOutputSampleRate(int).
ParameterssampleRateInHz    the sample rate expressed in Hz

So I wonder if you could set that for 1200 or 31250 or 9600 or whatever? Basic4Android seems to have some methods for bit manipulation so converting a byte/integer to bits and storing them in an array ought to be possible.
 
Upvote 0

Bob Katayama

Member
Licensed User
Longtime User
So I wonder if you could set that for 1200 or 31250 or 9600 or whatever? Basic4Android seems to have some methods for bit manipulation so converting a byte/integer to bits and storing them in an array ought to be possible.

Well, the MIDI standard is running at a baud rate of 31250. I am not sure if the data can be sent at any baud rate slower or faster to the USB port and have the USB MIDI interface convert this to 31250 or if the data should already be 31250 when sending to the USB port.

The existing support in Basic4Android should be sufficient to create serial code that could work with the USB MIDI interface.

Bob
 
Upvote 0

Bob Katayama

Member
Licensed User
Longtime User
The idea I have is to send data out of the audio socket and emulate the waveforms of a serial data stream.

The Red Eye Mini is an adapter for turning the iPhone into a TV remote controller.

RedEye mini: take control on the road

The Red Eye Mini uses the headphone jack therefore it must be doing something similar to what you want to send data as an audio stream.

Sending data as an audio stream is something I have never tried before thus cannot say if baud rates are a factor or not. I would say the receiving hardware connected to the audio socket would determine the rate in which the data can be processed.

Bob
 
Upvote 0

James Moxham

Member
Licensed User
Longtime User
That red-eye device looks interesting and shows that this is possible to do.

I got some of the code working last night. For the hardware, I am thinking a 1uF blocking capacitor, two 10ks in series to bias the volts to half the rail, then run that into an op amp comparator. Bias the other input of the comparator just below half the rail so the output is low when there is no audio. Then use another op amp so there is normal and inverted output. Also a max232 so there is normal, inverted and RS232 as the output. And maybe a transistor so the output is also midi compatible. That should cover a number of options. The hardware would be able to run to hundreds of kilohertz.

That is the theory anyway!
 
Upvote 0

Bob Katayama

Member
Licensed User
Longtime User
That red-eye device looks interesting and shows that this is possible to do.

I got some of the code working last night. For the hardware, I am thinking a 1uF blocking capacitor, two 10ks in series to bias the volts to half the rail, then run that into an op amp comparator. Bias the other input of the comparator just below half the rail so the output is low when there is no audio. Then use another op amp so there is normal and inverted output. Also a max232 so there is normal, inverted and RS232 as the output. And maybe a transistor so the output is also midi compatible. That should cover a number of options. The hardware would be able to run to hundreds of kilohertz.

That is the theory anyway!

Using the audio output to send a MIDI stream is intriguing but this limits MIDI for sending only (MIDI file or SYSEX data). I wonder what level of latency might be introduced when playing a MIDI file via this method?

Bob
 
Last edited:
Upvote 0

Bob Katayama

Member
Licensed User
Longtime User
I got some of the code working last night. For the hardware, I am thinking a 1uF blocking capacitor, two 10ks in series to bias the volts to half the rail, then run that into an op amp comparator. Bias the other input of the comparator just below half the rail so the output is low when there is no audio. Then use another op amp so there is normal and inverted output. Also a max232 so there is normal, inverted and RS232 as the output. And maybe a transistor so the output is also midi compatible. That should cover a number of options. The hardware would be able to run to hundreds of kilohertz.

That is the theory anyway!

Here is the standard MIDI interface diagram.

Electrical Specification for MIDI

Since using the audio output involves MIDI out only, can the MIC be used as the input? I am not sure if any of the existing Android tablets have an actual input jack or only the built in MIC though.

Just a thought on this.

Bob
 
Upvote 0

James Moxham

Member
Licensed User
Longtime User
Yes, good point re the band limiting. I expect a scope will answer that, and maybe 9600 is the fasted baud rate.

There should be some other solutions. eg use a propeller chip as a baud rate translater. Take an input at 9600 and output at MIDI rates. Latency ought to be no worse than a millisecond or so.

As for using the microphone as an input, hmm, it really is tricky to get data in and out of these devices.

I wonder if it is possible to program a chip like the propeller to emulate an sd card? I might ask over on the propeller forum.

Another thought - I see that Android has bluetooth in the software, though not all apads have bluetooth internally. Has anyone tried plugging in an external bluetooth dongle into the USB port? This thread says no http://android.stackexchange.com/questions/1198/how-to-use-an-android-device-as-bluetooth-usb-dongle but the Android world does change rapidly.
 
Last edited:
Upvote 0

James Moxham

Member
Licensed User
Longtime User
Yes, could be an option. Emulating a USB mass storage device will be better than emulating an SD card as it won't involve a hardware hack.

USB memory devices USB mass-storage device class - Wikipedia, the free encyclopedia and they mention The USB mass storage specification does not require any particular file system to be used on conforming devices. Instead, it provides a simple interface to read and write sectors of data—much like the low-level interface used to access any hard drive—using the "SCSI transparent command set."

So checking out SCSI SCSI - Wikipedia, the free encyclopedia down the bottom are some protocols. This stuff goes back to the 80s so hopefully is a fairly simple protocol.

Addit - this is an interesting read http://cache.freescale.com/files/microcontrollers/doc/ref_manual/DRM104.pdf
 
Last edited:
Upvote 0

James Moxham

Member
Licensed User
Longtime User
Making some progress with the code. I have yet to decode this on another chip, but the waveform looks plausible and it sounds like data when the Android plays it back. The idea is to create a .wav file, then play it. This is serial data, 8 bit, no parity, one stop bit. Polarity is inverse, ie resting is high, 0 is high and 1 is low. When run through a max232 that gets changed to resting is -12V.

The idea is to output at a slower baud rate, then use another chip, eg the propeller, to increase to MIDI baud rates.

Code is very "unrolled" at the moment as it makes debugging easier. See the attached waveform at the bottom.

B4X:
'Activity module
Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.
    Dim MediaPlayer1 As MediaPlayer
End Sub

Sub Globals
   'These global variables will be redeclared each time the activity is created.
   'These variables can only be accessed from this module.
   Dim AudioFile(88200) As Byte ' one second of sound
   Dim AudioFileCounter As Long
   Dim BytePacket(13) As Byte
End Sub

Sub Activity_Create(FirstTime As Boolean)
   Dim i As Int 
    Msgbox("Play a wav file", "First program")
   MediaPlayer1.Initialize( )
    MediaPlayer1.Load("/sdcard", "1200.wav")
   'Msgbox("Hit the home key to exit", "Finish")
   CreateWavHeader ' create the header 
   For i=1 To 10
      addbytetowav(0)
     addbytetowav(1)
     addbytetowav(2)
     addbytetowav(85)
     addbytetowav(255) 
   Next
   savewavfile
   playcreatedwav
   activity.finish ' close the program
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub
Sub SaveWavFile
    Dim raf As RandomAccessFile
   Msgbox("Saving to sd card","")
   raf.Initialize(File.DirDefaultExternal, "packet.wav", False)' open the file which will end up in I:\Android\data\test.test.test\files (test.test.test is my program)
   raf.WriteBytes(audiofile,0,88199, 0) ' write bytes. Is 32768 the max size as this is an integer variable
   raf.close
End Sub
Sub PlayCreatedWav
   MediaPlayer1.Initialize( )
    MediaPlayer1.Load(File.DirDefaultExternal , "packet.wav")
End Sub

Sub CreateWavHeader
   Dim i As Int 
    audiofile(0)=0x52 ' R
   audiofile(1)=0x49 ' I
   audiofile(2)=0x46 ' F
   audiofile(3)=0x46 ' F
   audiofile(4)=0x34 
   audiofile(5)=0xB1
   audiofile(6)=0x02 
   audiofile(7)=0x00 
   audiofile(8)=0x57 
   audiofile(9)=0x41 
   audiofile(10)=0x56 
   audiofile(11)=0x45 
   audiofile(12)=0x66 
   audiofile(13)=0x6D 
   audiofile(14)=0x74 
   audiofile(15)=0x20 
   
   audiofile(16)=0x10 
   audiofile(17)=0x00 
   audiofile(18)=0x00 
    audiofile(19)=0x00 
   audiofile(20)=0x01 
   audiofile(21)=0x00 
   audiofile(22)=0x01 
   audiofile(23)=0x00 
   audiofile(24)=0x44 
   audiofile(25)=0xAC 
   audiofile(26)=0x00 
   audiofile(27)=0x00 
   audiofile(28)=0x88 
   audiofile(29)=0x58 
   audiofile(30)=0x01 
   audiofile(31)=0x00 
   
   audiofile(32)=0x02 
   audiofile(33)=0x00 
   audiofile(34)=0x10 
    audiofile(35)=0x00 
   audiofile(36)=0x64 
   audiofile(37)=0x61 
   audiofile(38)=0x74 
   audiofile(39)=0x61 
   audiofile(40)=0x5C ' size in bytes (same as size of array = 88200 = 0x15888 minus the 44 bytes at the beginning 1585C)
   audiofile(41)=0x58 
   audiofile(42)=0x01 
   audiofile(43)=0x00 
   ' data starts at 44
   For i=44 To 99
     audiofile(i)=0 ' some zero values at the beginning of the file
   Next
   
   audiofilecounter=100' start of data
End Sub

Sub FillBytePacket
   Dim i As Int
   For i=0 To 13
      bytepacket(i)=65+i ' dummy values starting at A
   Next
End Sub

Sub AddByteToWav(ByteValue As Int) ' uses audiofilecounter
 ' wav file format is 0 for silence. values from -7FFF to 8000. LSB first. So FFFF is -1 which is just less than 0 for silence
 ' data starts at byte 43 https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
 ' so on hexedit, header is first two lines and 12 bytes of the third line
 ' the previous 4 bytes are the size of the data NumSamples * NumChannels * BitsPerSample/8
 ' this is a 1 channel sample.
 ' bytes 34 and 35 are the bits per sample = 0x0010 which is 16
 ' so size is numsamples * 1 * 16/ 8 which is numsamples *2
 ' the number of samples I have for 1 second of 1200 baud is 0x015876 which is 88182 or 44091 x 2.
 ' for a 1200 baud square wave this is high for 1/2400th of a second and low for 1/2400th second
 ' sample rate is 44100 per second. 
 ' for a 4410hz tone this will be high for 5 samples and low for 5 samples
 ' 1200 is 36.75 samples. 18.375 high and 18.375 low.
 ' BUT - 1200 baud means 1200 bits per second. So a character U will be 18.375 low then 18.375 high etc
 ' the start bit is 18.375 samples. 
 ' There are some aliasing issues here as well due to the remainder. This is 147/8
 ' so need to round to the nearest integer
 ' 18.375 =  18
 ' 36.75 =   37
 ' 55.125 =  55
 ' 73.5 =    74
 ' 91.875 =  91
 ' 110.25 =  110
 ' 128.625 = 129
 ' 147 =     147 
 ' 165.375 = 165
 ' 183.75 =  184
 ' 202.125 = 202
 ' 220.5 =   221 rounded up as this is the idle bit then start at zero again
 ' then restart on whole integer values 
 ' RS232 idle is -12V. Logical 1 is -12V. Logical 0 is +12V. Start bit is +12V. Stop bit is -12V
 ' So we use the inverse of this ready to go into a max232 
 ' idle = 5V, logical 1 is 5V, logical 0 is 0, Start bit is 0V, Stop bit is 5V
 ' so there is the start bit, 8 data bits, stop bit and an idle bit making 11 bits.
 ' set up a counter and start at 0
 ' 0-17 = start bit 
 ' 18-36 =  bit 0
 ' 37-54 =  bit 1
 ' 55-73 =  bit 2
 ' 74-90 =  bit 3
 ' 91-109 = bit 4
 ' 110-128= bit 5
 ' 129-146= bit 6
 ' 147-164= bit 7
 ' 165-183= stop bit
 ' 184-202= idle

 Dim i As Long
 Dim testvalue As Int
 Dim msb As Byte
 Dim lsb As Byte
 msb=0x7F
 lsb=0xFF
 For i=0 To 17 ' start bit
      audiofile(audiofilecounter)=lsb ' LSB
      audiofilecounter=audiofilecounter+1
      audiofile(audiofilecounter)=msb ' MSB
     audiofilecounter=audiofilecounter+1
 Next
 testvalue=Bit.And(bytevalue,0x01)' test bit 0
 If testvalue=0 Then 
     msb=0x7F ' hex 7FFF 
    lsb=0xFF
   Else
     msb=0x80 ' hex 8000
    lsb=0x00
 End If
 For i=18 To 36
      audiofile(audiofilecounter)=lsb ' LSB
      audiofilecounter=audiofilecounter+1
      audiofile(audiofilecounter)=msb ' MSB
     audiofilecounter=audiofilecounter+1
 Next
  testvalue=Bit.And(bytevalue,0x02)' test bit 1
 If testvalue=0 Then 
     msb=0x7F ' hex 7FFF 
    lsb=0xFF
   Else
     msb=0x80 ' hex 8000
    lsb=0x00
 End If
 For i=37 To 54
      audiofile(audiofilecounter)=lsb ' LSB
      audiofilecounter=audiofilecounter+1
      audiofile(audiofilecounter)=msb ' MSB
     audiofilecounter=audiofilecounter+1
 Next
  testvalue=Bit.And(bytevalue,0x04)' test bit 2
 If testvalue=0 Then 
     msb=0x7F ' hex 7FFF 
    lsb=0xFF
   Else
     msb=0x80 ' hex 8000
    lsb=0x00
 End If
 For i=55 To 73
      audiofile(audiofilecounter)=lsb ' LSB
      audiofilecounter=audiofilecounter+1
      audiofile(audiofilecounter)=msb ' MSB
     audiofilecounter=audiofilecounter+1
 Next
  testvalue=Bit.And(bytevalue,0x08)' test bit 3
 If testvalue=0 Then 
     msb=0x7F ' hex 7FFF 
    lsb=0xFF
   Else
     msb=0x80 ' hex 8000
    lsb=0x00
 End If
 For i=74 To 90
      audiofile(audiofilecounter)=lsb ' LSB
      audiofilecounter=audiofilecounter+1
      audiofile(audiofilecounter)=msb ' MSB
     audiofilecounter=audiofilecounter+1
 Next
  testvalue=Bit.And(bytevalue,0x10)' test bit 4
 If testvalue=0 Then 
     msb=0x7F ' hex 7FFF 
    lsb=0xFF
   Else
     msb=0x80 ' hex 8000
    lsb=0x00
 End If
 For i=91 To 109
      audiofile(audiofilecounter)=lsb ' LSB
      audiofilecounter=audiofilecounter+1
      audiofile(audiofilecounter)=msb ' MSB
     audiofilecounter=audiofilecounter+1
 Next
  testvalue=Bit.And(bytevalue,0x20)' test bit 5
 If testvalue=0 Then 
     msb=0x7F ' hex 7FFF 
    lsb=0xFF
   Else
     msb=0x80 ' hex 8000
    lsb=0x00
 End If
 For i=110 To 128
      audiofile(audiofilecounter)=lsb ' LSB
      audiofilecounter=audiofilecounter+1
      audiofile(audiofilecounter)=msb ' MSB
     audiofilecounter=audiofilecounter+1
 Next
  testvalue=Bit.And(bytevalue,0x40)' test bit 6
 If testvalue=0 Then 
     msb=0x7F ' hex 7FFF 
    lsb=0xFF
   Else
     msb=0x80 ' hex 8000
    lsb=0x00
 End If
 For i=129 To 146
      audiofile(audiofilecounter)=lsb ' LSB
      audiofilecounter=audiofilecounter+1
      audiofile(audiofilecounter)=msb ' MSB
     audiofilecounter=audiofilecounter+1
 Next
  testvalue=Bit.And(bytevalue,0x80)' test bit 7
 If testvalue=0 Then 
     msb=0x7F ' hex 7FFF 
    lsb=0xFF
   Else
     msb=0x80 ' hex 8000
    lsb=0x00
 End If
 For i=147 To 164
      audiofile(audiofilecounter)=lsb ' LSB
      audiofilecounter=audiofilecounter+1
      audiofile(audiofilecounter)=msb ' MSB
     audiofilecounter=audiofilecounter+1
 Next
 ' stop bit = high
 msb=0x80 
 lsb=0x00
 For i=165 To 183
      audiofile(audiofilecounter)=lsb ' LSB
      audiofilecounter=audiofilecounter+1
      audiofile(audiofilecounter)=msb ' MSB
     audiofilecounter=audiofilecounter+1
 Next
 ' idle bit = high and leave the rest high as well
 msb=0x80 
 lsb=0x00
 For i=184 To 202
      audiofile(audiofilecounter)=lsb ' LSB
      audiofilecounter=audiofilecounter+1
      audiofile(audiofilecounter)=msb ' MSB
     audiofilecounter=audiofilecounter+1
 Next
End Sub
 

Attachments

  • image1.jpg
    image1.jpg
    62.5 KB · Views: 354
Last edited:
Upvote 0

etLux

Member
Licensed User
Longtime User
Forgive me if this is a naive question -- but would it be
possible to modulate one of the device's LEDs as MIDI
output?

It would then be simple enough to build a receiver
circuit of a photo-transistor driving an op-amp into a
opto-isolator to create the MIDI output drive.

Best,


David
------
David Sosnowski
The Music of David Sosnowski
 
Last edited:
Upvote 0

James Moxham

Member
Licensed User
Longtime User
Hmm - worth thinking about, but I'm not sure my device has any leds that can be modulated.

I did think about a little solar cell over a section of the screen and turn that bit of the screen on and off. Maybe another small cell to act as a clock and then it could be a simple I2C type interface. It was a little slow though.

I've had some success with sending data out of the headphone jack.

B4X:
'Activity module
Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.
    Dim MediaPlayer1 As MediaPlayer
End Sub

Sub Globals
   'These global variables will be redeclared each time the activity is created.
   'These variables can only be accessed from this module.
   Dim AudioFile(88200) As Byte ' one second of sound
   Dim AudioFileCounter As Long
   Dim BytePacket(13) As Byte
End Sub

Sub Activity_Create(FirstTime As Boolean)
' see C:\Program Files\Android\android-sdk-windows\platform-tools 
' run the small batch file adb connect 192.168.2.6 where the IP address is the device address
' to get the IP address, Wifi settings, 3rd one down just under WiFi networks is the name of the network connected to
' Click this and it gives the signal strength and also the IP address
   Dim i As Int 
   Dim j As Int 
   Dim strings As String 
    'Msgbox("Play a wav file", "First program")
   'MediaPlayer1.Initialize( )
    'MediaPlayer1.Load("/sdcard", "1200.wav")
   CreateWavHeader ' create the header 
   addbytetowav(32)  ' space
   addbytetowav(13) ' carriage return
   addbytetowav(10) ' linefeed
   addbytetowav(72)  ' H
   addbytetowav(101) ' e   
   addbytetowav(108) ' l
   addbytetowav(108) ' l   
   addbytetowav(111) ' 0
   addbytetowav(32) '  space   
   addbytetowav(87) '  W
   addbytetowav(111) ' o
   addbytetowav(114) ' r
   addbytetowav(108) ' l   
   addbytetowav(100) ' d
   addbytetowav(13) ' CR
   addbytetowav(10) ' LF
   'For i=33 To 126
    '  addbytetowav(i) ' add ascii characters
   'Next
   CreateWavFooter
   savewavfile
   playcreatedwav
   activity.finish ' close the program
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub
Sub SaveWavFile
    Dim raf As RandomAccessFile ' see bottom corner of this program "Libraries" tab and check RandomAccessFile
   Msgbox("Saving to sd card","")
   raf.Initialize(File.DirDefaultExternal, "packet.wav", False)' open the file which will end up in I:\Android\data\test.test.test\files (test.test.test is my program)
   raf.WriteBytes(audiofile,0,88199, 0) ' write bytes. Is 32768 the max size as this is an integer variable
   raf.close
End Sub
Sub PlayCreatedWav
   MediaPlayer1.Initialize( )
    MediaPlayer1.Load(File.DirDefaultExternal , "packet.wav")
End Sub

Sub CreateWavHeader
   Dim i As Int 
    audiofile(0)=0x52 ' R
   audiofile(1)=0x49 ' I
   audiofile(2)=0x46 ' F
   audiofile(3)=0x46 ' F
   audiofile(4)=0x34 
   audiofile(5)=0xB1
   audiofile(6)=0x02 
   audiofile(7)=0x00 
   audiofile(8)=0x57 
   audiofile(9)=0x41 
   audiofile(10)=0x56 
   audiofile(11)=0x45 
   audiofile(12)=0x66 
   audiofile(13)=0x6D 
   audiofile(14)=0x74 
   audiofile(15)=0x20 
   
   audiofile(16)=0x10 
   audiofile(17)=0x00 
   audiofile(18)=0x00 
    audiofile(19)=0x00 
   audiofile(20)=0x01 
   audiofile(21)=0x00 
   audiofile(22)=0x01 
   audiofile(23)=0x00 
   audiofile(24)=0x44 
   audiofile(25)=0xAC 
   audiofile(26)=0x00 
   audiofile(27)=0x00 
   audiofile(28)=0x88 
   audiofile(29)=0x58 
   audiofile(30)=0x01 
   audiofile(31)=0x00 
   
   audiofile(32)=0x02 
   audiofile(33)=0x00 
   audiofile(34)=0x10 
    audiofile(35)=0x00 
   audiofile(36)=0x64 
   audiofile(37)=0x61 
   audiofile(38)=0x74 
   audiofile(39)=0x61 
   audiofile(40)=0x5C ' size in bytes (same as size of array = 88200 = 0x15888 minus the 44 bytes at the beginning 1585C)
   audiofile(41)=0x58 
   audiofile(42)=0x01 
   audiofile(43)=0x00 
   ' data starts at 44
   For i=44 To 99
     audiofile(i)=0 ' some zero values at the beginning of the file
   Next

   audiofilecounter=100' start of data

End Sub

Sub CreateWavFooter
   ' fill with zero (RS232 ends on 7FFF which is negative. So need to bring bias back to zero
   Dim i As Int
   For i=audiofilecounter To 88199
     audiofile(i)=0 ' change to zero
   Next
End Sub

Sub FillBytePacket
   Dim i As Int
   For i=0 To 13
      bytepacket(i)=65+i ' dummy values starting at A
   Next
End Sub

Sub AddByteToWav(ByteValue As Int) ' uses audiofilecounter
 ' wav file format is 0 for silence. values from -7FFF to 8000. LSB first. So FFFF is -1 which is just less than 0 for silence
 ' data starts at byte 43 https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
 ' so on hexedit, header is first two lines and 12 bytes of the third line
 ' the previous 4 bytes are the size of the data NumSamples * NumChannels * BitsPerSample/8
 ' this is a 1 channel sample.
 ' bytes 34 and 35 are the bits per sample = 0x0010 which is 16
 ' so size is numsamples * 1 * 16/ 8 which is numsamples *2
 ' the number of samples I have for 1 second of 1200 baud is 0x015876 which is 88182 or 44091 x 2.
 ' for a 1200 baud square wave this is high for 1/2400th of a second and low for 1/2400th second
 ' sample rate is 44100 per second. 
 ' ** addit - all the above is WRONG and it turns out this is a 2400 baud output ***
 ' for a 4410hz tone this will be high for 5 samples and low for 5 samples
 ' 1200 is 36.75 samples. 18.375 high and 18.375 low.
 ' BUT - 1200 baud means 1200 bits per second. So a character U will be 18.375 low then 18.375 high etc
 ' the start bit is 18.375 samples. 
 ' There are some aliasing issues here as well due to the remainder. This is 147/8
 ' so need to round to the nearest integer
 ' 18.375 =  18
 ' 36.75 =   37
 ' 55.125 =  55
 ' 73.5 =    74
 ' 91.875 =  91
 ' 110.25 =  110
 ' 128.625 = 129
 ' 147 =     147 
 ' 165.375 = 165
 ' 183.75 =  184
 ' 202.125 = 202
 ' 220.5 =   221 rounded up as this is the idle bit then start at zero again
 ' then restart on whole integer values 
 ' RS232 idle is -12V. Logical 1 is -12V. Logical 0 is +12V. Start bit is +12V. Stop bit is -12V
 ' translate this to 0/5 "true" logic levels where resting is 0V and the bits are inverted
 ' resting is 0V. Start bit is 5V. High is 0V. Low is 5V. Stop bit is 0V
 ' or "space", mark or space x8, "mark"
 ' "mark" is 7FFF, "space" Is 8000
 ' so there is the start bit, 8 data bits, stop bit and an idle bit making 11 bits.
 ' set up a counter and start at 0
 ' 0-17 = start bit 
 ' 18-36 =  bit 0
 ' 37-54 =  bit 1
 ' 55-73 =  bit 2
 ' 74-90 =  bit 3
 ' 91-109 = bit 4
 ' 110-128= bit 5
 ' 129-146= bit 6
 ' 147-164= bit 7
 ' 165-183= stop bit
 ' 184-202= idle

 Dim i As Long
 Dim testvalue As Int
 Dim msb As Byte
 Dim lsb As Byte
 msb=0x80
 lsb=0x00
 For i=0 To 17 ' start bit
      audiofile(audiofilecounter)=lsb ' LSB
      audiofilecounter=audiofilecounter+1
      audiofile(audiofilecounter)=msb ' MSB
     audiofilecounter=audiofilecounter+1
 Next
 testvalue=Bit.And(bytevalue,0x01)' test bit 0
 If testvalue=0 Then 
     msb=0x80 ' hex 8000 = space
    lsb=0x00
   Else
     msb=0x7F ' hex 7FFF = mark
    lsb=0xFF
 End If
 For i=18 To 36
      audiofile(audiofilecounter)=lsb ' LSB
      audiofilecounter=audiofilecounter+1
      audiofile(audiofilecounter)=msb ' MSB
     audiofilecounter=audiofilecounter+1
 Next
  testvalue=Bit.And(bytevalue,0x02)' test bit 1
 If testvalue=0 Then 
     msb=0x80 ' hex 8000 
    lsb=0x00
   Else
     msb=0x7F ' hex 7FFF
    lsb=0xFF
 End If
 For i=37 To 54
      audiofile(audiofilecounter)=lsb ' LSB
      audiofilecounter=audiofilecounter+1
      audiofile(audiofilecounter)=msb ' MSB
     audiofilecounter=audiofilecounter+1
 Next
  testvalue=Bit.And(bytevalue,0x04)' test bit 2
 If testvalue=0 Then 
     msb=0x80 ' hex 8000 
    lsb=0x00
   Else
     msb=0x7F ' hex 7FFF
    lsb=0xFF
 End If
 For i=55 To 73
      audiofile(audiofilecounter)=lsb ' LSB
      audiofilecounter=audiofilecounter+1
      audiofile(audiofilecounter)=msb ' MSB
     audiofilecounter=audiofilecounter+1
 Next
  testvalue=Bit.And(bytevalue,0x08)' test bit 3
 If testvalue=0 Then 
     msb=0x80 ' hex 8000 
    lsb=0x00
   Else
     msb=0x7F ' hex 7FFF
    lsb=0xFF
 End If
 For i=74 To 90
      audiofile(audiofilecounter)=lsb ' LSB
      audiofilecounter=audiofilecounter+1
      audiofile(audiofilecounter)=msb ' MSB
     audiofilecounter=audiofilecounter+1
 Next
  testvalue=Bit.And(bytevalue,0x10)' test bit 4
 If testvalue=0 Then 
     msb=0x80 ' hex 8000 
    lsb=0x00
   Else
     msb=0x7F ' hex 7FFF
    lsb=0xFF
 End If
 For i=91 To 109
      audiofile(audiofilecounter)=lsb ' LSB
      audiofilecounter=audiofilecounter+1
      audiofile(audiofilecounter)=msb ' MSB
     audiofilecounter=audiofilecounter+1
 Next
  testvalue=Bit.And(bytevalue,0x20)' test bit 5
 If testvalue=0 Then 
     msb=0x80 ' hex 8000 
    lsb=0x00
   Else
     msb=0x7F ' hex 7FFF
    lsb=0xFF
 End If
 For i=110 To 128
      audiofile(audiofilecounter)=lsb ' LSB
      audiofilecounter=audiofilecounter+1
      audiofile(audiofilecounter)=msb ' MSB
     audiofilecounter=audiofilecounter+1
 Next
  testvalue=Bit.And(bytevalue,0x40)' test bit 6
 If testvalue=0 Then 
     msb=0x80 ' hex 8000 
    lsb=0x00
   Else
     msb=0x7F ' hex 7FFF
    lsb=0xFF
 End If
 For i=129 To 146
      audiofile(audiofilecounter)=lsb ' LSB
      audiofilecounter=audiofilecounter+1
      audiofile(audiofilecounter)=msb ' MSB
     audiofilecounter=audiofilecounter+1
 Next
  testvalue=Bit.And(bytevalue,0x80)' test bit 7
 If testvalue=0 Then 
     msb=0x80 ' hex 8000 
    lsb=0x00
   Else
     msb=0x7F ' hex 7FFF
    lsb=0xFF
 End If
 For i=147 To 164
      audiofile(audiofilecounter)=lsb ' LSB
      audiofilecounter=audiofilecounter+1
      audiofile(audiofilecounter)=msb ' MSB
     audiofilecounter=audiofilecounter+1
 Next
 ' stop bit = "mark"
 msb=0x7F 
 lsb=0xFF
 For i=165 To 183
      audiofile(audiofilecounter)=lsb ' LSB
      audiofilecounter=audiofilecounter+1
      audiofile(audiofilecounter)=msb ' MSB
     audiofilecounter=audiofilecounter+1
 Next
 ' idle bit = mark and leave in this state
 msb=0x7F 
 lsb=0xFF
 For i=184 To 202 ' time to resynch
      audiofile(audiofilecounter)=lsb ' LSB
      audiofilecounter=audiofilecounter+1
      audiofile(audiofilecounter)=msb ' MSB
     audiofilecounter=audiofilecounter+1
 Next
End Sub

Decode it with a LM324 and then a max232. Send the data back into the PC and display it on a terminal program. See attached.

It needs some work:
1) Despite all my maths for 1200 baud, it turned out to be 2400 baud. I must be getting my periods and frequencies muddled up!
2) It is writing to the sd card each time it needs to play a wav file. I think there are some new audio drivers coming very soon (Yay!)
3) There must be a way of using the strings function to turn "Hello World" into a series of integers rather than sending them out with
addbytetowav(72) ' H
4) If we can get data out of this we can convert it to other data, eg a 2400 baud to Midi converter, maybe on the Propeller chip?
5) What is the prefix for hex data? Basic used to use &H but this gave an error so I took a lucky guess with 0xFF and this worked. More specifically, where in the help is this, and does the description talk about other formats eg binary?

This is all great fun!
 

Attachments

  • image2.jpg
    image2.jpg
    8.2 KB · Views: 285
Upvote 0

ZJP

Active Member
Licensed User
Longtime User
@James Moxham : Very complicated.
@Erel : Is it possible with the new audio library to generate a sound (such as: Sound (frequency, duration))?

Because with a NE567, the solution would be simpler. :)

JP
 
Last edited:
Upvote 0

AndyDroid2012

Member
Licensed User
Longtime User
MIDI USB Control

Hi Guys,
Can I add a few thoughts here.

1. MIDI USB data will be IN or OUT and consist of a Channel number and a numeric data value as far as I can tell.
So, a piano key press would be data IN with the note value and if possible attack, decay information as a second or multiple data stream.
i.e. its not a wav file or any audio voltage but digital coding.
Playing MIDI out would be the same data in reverse.

2. There is an app called USB MIDI MONITOR which says it can monitor and display incoming midi from say a piano, so it should be possible to save such a data stream and later send it out, maybe with a different channel number for OUT and hear the music playing.

3. Apps such as TouchDAW and others are concentrating on bluetooth because it makes sense to control multiple hardware devices wirelessly to save clutter for one thing, but based on points 1 and 2 it should be the same logic to send out of USB to a wired USB MIDI adapter such as the Xmidi 1x1 which I have. (and the reason for my interest in Basic4android)

4. Years ago I was partly involved in creating a midi driver for Windows which was programatically a dog and then later on, testing a USB to PIC controller to burn a PIC microprogram. It had its own Windows USB driver. At the time it seemed that writing MS Visual Basic (VB6) to communicate with the USB was fraught with problems and I abandoned further development.

So, I think its a case of knowing how a meaningful data stream is constructed and sending it to the USB port, or receiving that data and parsing it into MIDI data before saving it to a midi file. That info ought to be somewhere on the internet.
 
Upvote 0
Top