-
-
Notifications
You must be signed in to change notification settings - Fork 177
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Trying to record program from old computer #175
Comments
Are you using the sdfat library? Is much faster than the stock SD lib and recording is much better.
One thing to note is TMRpcm uses PWM so a series of square waves to replicate audio. If playing simple tones certain frequencies will sound odd due to harmonics. Not much can be done about that.
… On Sep 12, 2022, at 4:48 AM, rickyelqasem ***@***.***> wrote:
I have a lot of inconsistency while trying to record programs from old computers. If the program is short, the a better chance I will be able to load it later. Playback using my circuit is perfect because if I load a program that was converted to a wav using a converter on my PC, playback works every time. Programs recorded(32000) to wav using this library hardly playback. I've played around with amplification, but I don't think it's that. I think the library is adding artefacts to the sound wave. So for example a good file might play a single flat tone, while if it's recorded using the library, I hear a warble or ringing when there should be a flat tone. I can dropbox you an example of a good/bad file. Any advice to improve? BTW I cannot increase buffsize past 76 due to the lack of memory taken by the rest of the firmware. thx
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.
|
if I use a sine to square wave converter, do you think I will get a better response? also I just updated SDfat to see if I get better results. |
Don’t think you’d have much luck with a converter. Hope sdfat helps!
… On Sep 12, 2022, at 6:27 AM, rickyelqasem ***@***.***> wrote:
if I use a sine to square wave converter, do you think I will get a better response? also I just updated SDfat to see if I get better results.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you commented.
|
Ahh, I'm going to assume this is related to using interrupts to drive everything. In a blog post a long while back, I did some experimentation with high speed signaling on Arduino, and found that using interrupts, things can be a bit choppy, as far as the timing of things goes. Since we are using nested interrupts here, I'll assume that is the problem. In that post there is some assembly code that more or less regulates the timing of interrupts, so they occur at the same time, every time. I could possibly be modified to work with TMRpcm, but I have not had time to experiment with it.
This would be called from inside one of the interrupts in TMRpcm. If it is fast enough for 8mhz signaling, I assume it would smooth out the output of TMRpcm as well, but again I haven't had time to experiment. You would need to change TCNT1 to the value of one of the timers used in playback/recording of TMRpcm. (I have to review the code to figure this all out) I think you could use TCNT1, but again I have to review the code. All in all, TMRpcm isn't 100% accurate in its reproduction of audio, but this may smooth things out a bit if it can be gotten working. I'll see if I have time over the next days/week or so to play around with it. Unfortunately I don't have an oscilloscope so can't see the waveforms created. |
Happy help test. I have a cheap signal generator and an oscilloscope. |
(To start: I can reproduce the same problems rickyelqasem reported) I (think I) see a few problems in the code. But please take all this with a huge grain of salt / open-mindedness just because I'm going thru the code and the datasheet at the same time, and may well be misunderstanding a few things. Firstly, it looks like it's signalling the wrong buffer to write next (should be bufferEmpty[whichBuffer]=0 , not bufferEmpty[!whichBuffer]=0, in the TIMER1_COMPB_vect). Basically, the first buffer to fill (which is whichBuffer) should be the first buffer to write, but the code signals the other buffer to be written next. Secondly, I think, the ISR priorities are wrong - the write-to-sd ISR (COMPA) has a higher priority than the read-adc-to-buffer (COMPB), so the write to sd interrupts actually filling the buffer. Probably this is causing lost samples. I think this probably the main issue. I can kindof see why (the ADC is tied to Timer1 COMPB). Maybe using COMPA is wrong here then, and should just use TIMER1_OVF_vect instead. In other words, keep COMPB for adc, and use a lower priority (rather than a higher priority) ISR for dumping buffers to sd. As I understand it, you cannot record and playback different things at the same time anyway (there's only one buffer after all), so I don't see why TIMER1_OVF_vect couldn't dual-purpose for playback usage (i.e. what it's currently doing) and recording usage (i.e. the write-to-sd). So just "if recording then.." at the start of the ISR. Maybe a couple of other problems related to COMPB : the OCR1B isn't ever explicitly initialised in the recording setup, but it is used in the Speaker2 logic, so it could arbitrarily be wrong at this point. (Guessing it should be reset to 0 when you start recording). I'm not sure I quite understand the TIMER1_CAPT_vect - I guess it's just toggling the enable and then waking itself up repeatedly - neat trick if so! But then wouldn't that also work for recording (as an alternative to the above suggestion) - use the TIMER1_CAPT_vect for dumping buffers to sd in recording mode - in the same way it's being used to read buffers from sd in playback mode? I haven't tried implementing all the above (I started having a play around swapping the COMPA and COMPB ISRs but I forget to change the OC1E1A for OC1E1B, got into an infinite loop during writing to sd and actually totally trashed two sd cards, so I need to purchase some more first before I can retest!) I think there might also be a bug in playback (unrelated to this), just from reading the code anyway - I'll open a separate ticket for that |
You think this is causing the frequency blips?
…On 8 Oct 2022, 16:04 +0100, Dave Hooper ***@***.***>, wrote:
I (think I) see a few problems in the code. But please take all this with a huge grain of salt / open-mindedness just because I'm going thru the code and the datasheet at the same time, and may well be misunderstanding a few things.
Firstly, it looks like it's signalling the wrong buffer to write next (should be bufferEmpty[whichBuffer]=0 , not bufferEmpty[!whichBuffer]=0, in the TIMER1_COMPB_vect). Basically, the first buffer to fill (which is whichBuffer) should be the first buffer to write, but the code signals the other buffer to be written next.
Secondly, I think, the ISR priorities are wrong - the write-to-sd ISR (COMPA) has a higher priority than the read-adc-to-buffer (COMPB), so the write to sd interrupts actually filling the buffer. Probably this is causing lost samples. I think this probably the main issue.
I can kindof see why (the ADC is tied to Timer1 COMPB). Maybe using COMPA is wrong here then, and should just use TIMER1_OVF_vect instead. In other words, keep COMPB for adc, and use a lower priority (rather than a higher priority) ISR for dumping buffers to sd.
As I understand it, you cannot record and playback different things at the same time anyway (there's only one buffer after all), so I don't see why TIMER1_OVF_vect couldn't dual-purpose for playback usage (i.e. what it's currently doing) and recording usage (i.e. the write-to-sd). So just "if recording then.." at the start of the ISR.
Maybe a couple of other problems related to COMPB : the OCR1B isn't ever explicitly initialised in the recording setup, but it is used in the Speaker2 logic, so it could arbitrarily be wrong at this point. (Guessing it should be reset to 0 when you start recording).
I'm not sure I quite understand the TIMER1_CAPT_vect - I guess it's just toggling the enable and then waking itself up repeatedly - neat trick if so! Wouldn't that also work for recording (as an alternative to the above suggestion) - use the TIMER1_CAPT_vect for dumping buffers to sd in recording mode - in the same way it's being used to read buffers from sd in playback mode?
I think there might also be a bug in playback (unrelated to this), just from reading the code anyway - I'll open a separate ticket for that
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you authored the thread.Message ID: ***@***.***>
|
Yeah
…On Sat, 8 Oct 2022, 16:57 rickyelqasem, ***@***.***> wrote:
You think this is causing the frequency blips?
On 8 Oct 2022, 16:04 +0100, Dave Hooper ***@***.***>, wrote:
> I (think I) see a few problems in the code. But please take all this
with a huge grain of salt / open-mindedness just because I'm going thru the
code and the datasheet at the same time, and may well be misunderstanding a
few things.
> Firstly, it looks like it's signalling the wrong buffer to write next
(should be bufferEmpty[whichBuffer]=0 , not bufferEmpty[!whichBuffer]=0, in
the TIMER1_COMPB_vect). Basically, the first buffer to fill (which is
whichBuffer) should be the first buffer to write, but the code signals the
other buffer to be written next.
> Secondly, I think, the ISR priorities are wrong - the write-to-sd ISR
(COMPA) has a higher priority than the read-adc-to-buffer (COMPB), so the
write to sd interrupts actually filling the buffer. Probably this is
causing lost samples. I think this probably the main issue.
> I can kindof see why (the ADC is tied to Timer1 COMPB). Maybe using
COMPA is wrong here then, and should just use TIMER1_OVF_vect instead. In
other words, keep COMPB for adc, and use a lower priority (rather than a
higher priority) ISR for dumping buffers to sd.
> As I understand it, you cannot record and playback different things at
the same time anyway (there's only one buffer after all), so I don't see
why TIMER1_OVF_vect couldn't dual-purpose for playback usage (i.e. what
it's currently doing) and recording usage (i.e. the write-to-sd). So just
"if recording then.." at the start of the ISR.
> Maybe a couple of other problems related to COMPB : the OCR1B isn't ever
explicitly initialised in the recording setup, but it is used in the
Speaker2 logic, so it could arbitrarily be wrong at this point. (Guessing
it should be reset to 0 when you start recording).
> I'm not sure I quite understand the TIMER1_CAPT_vect - I guess it's just
toggling the enable and then waking itself up repeatedly - neat trick if
so! Wouldn't that also work for recording (as an alternative to the above
suggestion) - use the TIMER1_CAPT_vect for dumping buffers to sd in
recording mode - in the same way it's being used to read buffers from sd in
playback mode?
> I think there might also be a bug in playback (unrelated to this), just
from reading the code anyway - I'll open a separate ticket for that
> —
> Reply to this email directly, view it on GitHub, or unsubscribe.
> You are receiving this because you authored the thread.Message ID:
***@***.***>
—
Reply to this email directly, view it on GitHub
<#175 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABF47HHFATUATWRT4LO5EBTWCGKXZANCNFSM6AAAAAAQKK3ZAM>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
Heh, nice analysis. I'd have to really review the code and datasheet to see what your analysis means for the code. If you have time to play around with the code and analyze things in more detail, please do. Pull requests are welcome if you are able to put something together that improves functionality! I've developed the library without the use of an oscilloscope, so there may be a few issues here or there that need to be figured out in greater detail. |
Yep, I'll try something out. I don't have an oscilloscope either (wouldn't know how to use one even if I did). I'll just get rid of the COMPA_vect (which interrupts the sampling because its higher than COMPB) and use the CAPT or OVF instead (which is lower than COMPB) |
After some more experiments I think I've convinced myself that the interrupt priority was a red-herring and wouldn't have a significant impact on fixing this. I don't see (hear) any evidence of dropped samples on the 'rec+thru' mode, which would be the case if writing to sd was somehow blocking sample capture. So I think you can disregard the "Secondly" comments above :-/ The first part does still seem to be a bug, but not a significant one (it seems to lessen the problem, for me anyway, but not remove it). A more significant improvement seems to be from making the buffer bigger. |
"Also tested it with a signal generator using a fixed frequency and still got the anomalies. This wave should be uniform." @rickyelqasem Do you recall what fixed frequency you were using and what sample rate you were recording at? |
3khz and 22050 .
…On 9 Oct 2022, 13:26 +0100, TMRh20 ***@***.***>, wrote:
"Also tested it with a signal generator using a fixed frequency and still got the anomalies. This wave should be uniform."
@rickyelqasem Do you recall what fixed frequency you were using and what sample rate you were recording at?
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
In my case used the example Recorder sketch included in this repo, which
records at 16000hz, and my input was a simple sine wave frequency sweep
(from 0 to 22050 hz) generated on a PC (GoldWave can do this, or e.g. I'm
sure Audacity can also). That was good at making a lot of glitches
apparent. I heard the same glitches both playing back the file on device
from the sketch, and playing the resultant wav into the PC.
…On Sun, 9 Oct 2022, 13:46 rickyelqasem, ***@***.***> wrote:
3khz and 22050 .
On 9 Oct 2022, 13:26 +0100, TMRh20 ***@***.***>, wrote:
> "Also tested it with a signal generator using a fixed frequency and
still got the anomalies. This wave should be uniform."
> @rickyelqasem Do you recall what fixed frequency you were using and what
sample rate you were recording at?
> —
> Reply to this email directly, view it on GitHub, or unsubscribe.
> You are receiving this because you were mentioned.Message ID:
***@***.***>
—
Reply to this email directly, view it on GitHub
<#175 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABF47HETUHS3JQ3WZJVLOD3WCK5A7ANCNFSM6AAAAAAQKK3ZAM>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
If that's the case, then I'm thinking you're getting dropped samples. The best way to work around this would be to increase the buffer size as @stripwax mentioned, as well as using the SDFat library with potentially a lower recording sample rate. It should lose less samples that way. |
Yes tried much lower sample rates and different speeds of sd cards and still get the sample drops. Only thing I struggle to test is more buffer as I cannot squeeze and more sram. I can try it with the example stretch.
…On 9 Oct 2022, 13:55 +0100, TMRh20 ***@***.***>, wrote:
If that's the case, then I'm thinking you're getting dropped samples. The best way to work around this would be to increase the buffer size as @stripwax mentioned, as well as using the SDFat library with potentially a lower recording sample rate. It should lose less samples that way.
In this case, there is probably not much that I can to library-wise to fix it unless we can identify some bugs, but I have a feeling the main issue is the speed of the microcontroller not being able to keep up. If you reduce the sample rate to say 16khz and record a 3khz sample, do you end up with the same inconsistencies or does it help? If so there may be some buggy behaviour, if not I would assume an MCU speed issue.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
If you're getting sample drops at low sample rates, something is probably wrong somewhere. Not sure how to go about addressing this without a scope though... I'll see what I can figure out. |
I still think it’s the timers.. increasing buffer, lower sample rate and faster sd made no real difference. If you look at the picture below TMRpcm+Arduino the squarewave is not constant. The width is constantly changing. Whereas recording on a PC with a sound card the width(frequency) is pretty constant.
From: TMRh20 ***@***.***>
Sent: 09 October 2022 14:23
To: TMRh20/TMRpcm ***@***.***>
Cc: rickyelqasem ***@***.***>; Mention ***@***.***>
Subject: Re: [TMRh20/TMRpcm] Trying to record program from old computer (Issue #175)
If you're getting sample drops at low sample rates, something is probably wrong somewhere. Not sure how to go about addressing this without a scope though... I'll see what I can figure out.
—
Reply to this email directly, view it on GitHub <#175 (comment)> , or unsubscribe <https://github.com/notifications/unsubscribe-auth/ACRRWCFSQVMPBZIF3R4PHO3WCLBNBANCNFSM6AAAAAAQKK3ZAM> .
You are receiving this because you were mentioned. <https://github.com/notifications/beacon/ACRRWCHXVS7HSAIBWS5U623WCLBNBA5CNFSM6AAAAAAQKK3ZAOWGG33NNVSW45C7OR4XAZNMJFZXG5LFINXW23LFNZ2KUY3PNVWWK3TUL5UWJTSL3FZ5C.gif> Message ID: ***@***.*** ***@***.***> >
|
@rickyelqasem I don't think it's (just) the timers - your first screenshot shows quite a lot of clipping and a dc offset. The periods you're pointing to have different shaped tops and bottoms, true, but that's more likely to be an analogue artifact. Measuring peak-to-peak should be fairly constant. Those screenshots actually look pretty OK. |
Here's a prototype showing the changes I had in mind, but it's totally untested right now. I'll see if any of this makes any difference in practice. https://github.com/stripwax/TMRpcm/tree/recording_fixes. (UPDATED) I've tested this and I'm pretty happy with it. With a buffer of 254 I get zero pops/clicks, but I still get problems with a buffer size of 128. However, if I also set the following flag, for SDFat, I get clean output with a buffer size of 128: Without my changes, I hear an audible blip/glitch in the output around every one or two seconds when buffer size is 128, and worse when buffer size is 64, and setting the CHECK_FLASH_PROGAMMING flag doesn't seem to make a difference. I'm fairly certain these results are repeatable and reproducible My setup is just Timer1 with a Arduino Nano (Mega328p), and mono 8 bit. I've not tried/tested any of the USE_TIMER2 / MODE2 / DUAL / STEREO / 16bit combinations, or stuff for other devices, so even though I have those changes in my branch too, those are totally untested. And I've not tested playback/loops/etc, other than through the example sketch playing back what I just recorded. |
@stripwax Wow lots of changes, nice stuff! Not many people that understand timers and interrupts to this degree, and even having written the code it will take me some time to go through it as well as test. |
I have a lot of inconsistency while trying to record programs from old computers. If the program is short, the a better chance I will be able to load it later. Playback using my circuit is perfect because if I load a program that was converted to a wav using a converter on my PC, playback works every time. Programs recorded(32000) to wav using this library hardly playback. I've played around with amplification, but I don't think it's that. I think the library is adding artefacts to the sound wave. So for example a good file might play a single flat tone, while if it's recorded using the library, I hear a warble or ringing when there should be a flat tone. I can dropbox you an example of a good/bad file. Any advice to improve? BTW I cannot increase buffsize past 76 due to the lack of memory taken by the rest of the firmware. thx
The text was updated successfully, but these errors were encountered: