Saturday 11 February 2012

Panasonic JR200u tape wave generation


I've previously described the contents of a CJR file and the structuring of the Panasonic JR200U tape format. Here I'll go into converting binaries into WAV audio files that work as JR200 tape input. The purpose is to produce similar audio files as would result when an output from the actual machine is recorded. It's pretty straightforward except for the fact that the tape audio consists of data encoded both in 600 and 2400 baud speeds, and the way of encoding for the two is a bit different.

I'll take a very brutal and practical approach and merely tell how to construct a wave file that can be played back to the Panasonic from an audio software such as Audacity. This is just a crude task of appending bytes into a file in a correct order, and the finer points about signal processing can and will be ignored. First I will describe how bytes are composed in an audio file both in the 600 baud format and the 2400 baud format and how to append them into the WAV as waveform data points. Only after then the overall layout of the wave file with all the necessary "filler" will be given.

The following will work with the assumption that the file consists of a 600 baud header and 2400 baud data blocks. The logic of a full 600 baud file is slightly different, and simply using 600 baud binary with the below description will not work. For completeness sake, this may be addressed in the future, but as the 2400 baud format is the more useful the lower speed is ignored for now.

If you just need a tool for converting CJR files, head to this page.

The header bytes

Looking in detail at a tape audio wave in Audacity, it can be seen the data is encoded in a square wave.



This is the beginning of a header block after a lead in. A block in a normal file always seems to begin with a 2 and 42. (See the previous blog entry for the composition of the CJR files.)

The bytes are of course built out of bits, and these bits are represented in the header wave as a group of longer and shorter waves. The longer wavelength is 1 and the shorter is 0.

So, the above wave will translate into bits like this:

...11111110010000001110010101001110...

The highlighted parts are the same as are highlighted in the image above. The "nybbles" of 1110 are byte markers that precede all actual data bytes. They are not part of the stored data content. The lead-in and all in-between sounds are long series of 1's without the nybbles.

I have previously illustrated the composition of a byte in the header, and here it is again. The format is little-endian binary. This is the composition for the Ascii character 's' (Decimal 115):



The following byte marker actually belongs to the next byte already, which is not visible. Building the header as a wave with this information is then quite simple. For each data byte, the byte marker bits and the data bit waves are appended to the wave file.

But how many audio samples does each bit result in the actual wave file?

I'm assuming a 44100hz sample rate for the WAV, as to simplify the practical task of constructing the file. Note that what follows is not ideal, for reasons given later in the text.

This is the procedure for making the bits:

Do 0: Make the datapoints for a 0-bit:

Write 8 data points of negative signal
Write 1 data point of neutral signal
Write 8 data points of positive signal
Write 1 data point of neutral signal
Write 8 data points of negative signal
Write 1 data point of neutral signal
Write 8 data points of positive signal
Write 1 data point of neutral signal
Write 8 data points of negative signal
Write 1 data point of neutral signal
Write 8 data points of positive signal
Write 1 data point of neutral signal
Write 8 data points of negative signal
Write 1 data point of neutral signal
Write 8 data points of positive signal
Write 1 data point of neutral signal

Do 1: Make the datapoints for a 1-bit:

Write 17 data points of negative signal
Write 1 data point of neutral signal
Write 17 data points of positive signal
Write 1 data point of neutral signal
Write 17 data points of negative signal
Write 1 data point of neutral signal
Write 17 data points of positive signal
Write 1 data point of neutral signal

Both take 72 data points in the wave file. In an 8-bit wave, this would be the actual number of bytes, whereas in a 16-bit wave, the amount will be double. I have myself used 16-bit waves, although 8-bit (or even less) might suffice.

Just to reiterate the obvious, using the above logic the character 's' as in the previous image would be built like this:

Do 1, Do 1, Do 1, Do 0. [The byte marker nybble]
Do 1, Do 1, Do 0, Do 0, Do 1, Do 1, Do 1, Do 0. [The character 's' in ascii]

The 2400 baud format

The 2400 baud format is slightly more difficult to illustrate. When visualized, the bits are not a set of consistently identical peaks and valleys.



The above image is a portion of the wave where the data begins in 2400 baud format. The construction of the short and the long wave does not differ, but the data is 4 times more dense than in 600 baud format.

Although the image highlights the nybbles very clearly, it is not so obvious how the data bytes are composed. The image shows bytes 2 and 42 as before, but they don't look quite the same. So, the difference between 600 and 2400 baud format is not simply a question of changed frequency.

The data is there in the same little-endian way, it is just that the waves representing ones and zeroes can be "upside down". Let's have a visual look at one of the bytes, the 42.



The illustration already makes things much clearer. The first '1' within the byte points "down", whereas the second one points "up". Also, the three one's in the nybble point to alternate directions. But, looking at the two last zeroes, they are identical. So it is the '1' that changes the phase.

Both the above images are misleading in that the nybble byte markers seem identical. They can also be inverted, depending on the previous bit phase, it just happens so the chosen images do not show this.

To cut the explanation, here's the procedure for making the bits in a 2400 baud format:

(The A-signal is initially negative, as the last 1-bit in the 600 baud format part implies.)

Do 0: Make the datapoints for a 0-bit:

Write 8 data points of A-signal
Write 1 data point of neutral signal
Invert the A-signal
Write 8 data points of A-signal
Write 1 data point of neutral signal
Invert the A-signal

Do 1: Make the datapoints for a 1-bit:

Write 17 data points of A-signal
Write 1 data point of neutral signal
Invert the A-signal

So, how each bit "looks like" in the wave depends on what the state of A was after the previous bit was written. So unlike in the 600 baud format, the wave writer needs to keep record of this phase.

A note about the approach

This method as described will not generate precisely same overall wave file lengths as recorded from the Panasonic. Some adjustment may be required to achieve this. In reality, the wavelength is not "72 bytes" long, but a frequency. The described approach is in a way inferior to one where a real frequency is used. This method does work, though, so it will suffice here. Also, this procedural approach is simpler to explain.

In my wave generator, I added a global time skip variable that can be used to adjust the overall synchronization of the wave. The time skip can be adjusted so that the overall audio file lengths would better correspond with those of the actual machine. This means that data points are counted as they are written into the WAV, and each hundredth (say) will not be written. Or if the audio file needs to be lengthened, every hundredth data point will be written twice, or something like that.

The overall wave generation

The more tricky stuff has been gone through and what is left is to give the recipe for generating the whole audio file. For the content of the Blocks, refer to the previous blog post.

600 baud header:

 Generate some silence
 Lead in: More than 800 bits of 1
 Header Block: 33 bytes in the 600 baud format above
 In-Betweener: 51 bits of 1

2400 baud data blocks and footer/tail:

 Data Block 1
 In-betweener: 196 bits of 1
 Data Block 2
 In-betweener: 196 bits of 1
 Data Block 3
 In-betweener: 196 bits of 1
 ...
 ...
 Last Data Block
 A "long 1", See *1
 In-Betweener: 188 bits of 1
 Footer Block (tail)
 Byte 255, See *2
 Lead out: some 150 bits of 1
 Generate some silence (5 seconds between tape parts for example)

*1: The Long 1 is an anomalous piece of waveform that seems to be added at this point. It can be treated as a 1 that has twice as long waveform. I'm not sure if Panasonic really requires this, but it's better to be precise.
*2: The byte 255 is not included in a CJR file.



The above image shows the anomalous waveform near the end of a file, before the footer. Looking the image closer will also reveal the number of samples used for the waves. (36 as opposed to the 17 in the following wave.)

The WAV format

Describing the actual wave file format is really outside the scope of this post, but I'll include the bare description for writing 16-bit, one channel, 44100hz sound files. So, again, the following is just for the purposes of generating the things discussed above, and it is not intended to be a full WAV specification. The alphabetic values are in Ascii.

An easy formula for the entire file size [offset 4-7] is 44+seconds*88200.

0    : R
1    : I
2    : F
3    : F
4-7  : 32 bit value for the entire file size
8    : W
9    : A
10   : V
11   : E
12   : f
13   : m
14   : t
15   : 32 [space]
16   : 16 [16-bit pcm]
17   : 0
18   : 0
19   : 0
20   : 1 [audioformat=1]
21   : 0
22   : 1 [numchannels=mono]
23   : 0
24-27: 44100 [32-bit value for sample rate]
28-31: 88200 [32-bit value for byte rate]
32   : 2 [block alignment]
33   : 0
34   : 16 [bits per sample]
35   : 0
36   : d
37   : a
38   : t
39   : a
40-43: [32 bit value for the wave chunk size]
44-  : [16 bit words for the single channel wave data.]




No comments:

Post a Comment