# KOSMO Audiohacker - looking for mistakes/feedback

**URL:** <https://lookmumnocomputer.discourse.group/t/kosmo-audiohacker-looking-for-mistakes-feedback/2374>\
**Category:** KOSMO MODULES\
**Created:** [November 25, 2020, 8:53pm UTC](https://lookmumnocomputer.discourse.group/t/kosmo-audiohacker-looking-for-mistakes-feedback/2374 "2020-11-25T20:53:53Z")\
**Posts on this page:** 11\
**Page:** 2

<div class="post-metadata">

**Author:** ![sebastian](https://yyz2.discourse-cdn.com/free1/user_avatar/lookmumnocomputer.discourse.group/sebastian/32/39_2.png) [@sebastian](https://lookmumnocomputer.discourse.group/u/sebastian)\
**Post date:** [December 13, 2020, 9:26pm UTC](https://lookmumnocomputer.discourse.group/t/kosmo-audiohacker-looking-for-mistakes-feedback/2374/21 "2020-12-13T21:26:35Z")

</div>

Thank you again, I think I have a somewhat okay module now. I will order in a few days and see how it works out! (Then I still need to manage the software part, assuming that the hardware is okay).  
I made the panel today: 🙂 Pretty happy, just thinking if I need to rename some of the stuff.

 ![Screenshot from 2020-12-13 22-06-07](https://global.discourse-cdn.com/free1/uploads/lookmumnocomputer/original/2X/4/49ca936f164545083e57b2fe84d967cfc66c0ec3.png)

---

<div class="post-metadata">

**Author:** ![sebastian](https://yyz2.discourse-cdn.com/free1/user_avatar/lookmumnocomputer.discourse.group/sebastian/32/39_2.png) [@sebastian](https://lookmumnocomputer.discourse.group/u/sebastian)\
**Post date:** [February 3, 2021, 9:35pm UTC](https://lookmumnocomputer.discourse.group/t/kosmo-audiohacker-looking-for-mistakes-feedback/2374/22 "2021-02-03T21:35:06Z")

</div>

I have not yet ordered, too much other stuff happening…  
I was wondering however if my bypass will work as I intended:

 ![Screenshot from 2021-02-03 22-27-01](https://global.discourse-cdn.com/free1/uploads/lookmumnocomputer/original/2X/3/3c7a8013abb3d4f964dd7f02621eb609ab92a35c.png)

 ![Screenshot from 2021-02-03 22-24-35](https://global.discourse-cdn.com/free1/uploads/lookmumnocomputer/original/2X/1/1fbb372a017b1dc430f3b96b5b54aea01e17ec6f.png)

I use one side of the dpdt for the LED and the other connects the audio in jack to  
(1) opamps and then ADC, or, if the switch is turned to “off” (2) directly to the audio out jack. Is the output of the DAC still being connected to the output jack a problem? It should be at 0 volt when there is no signal coming in, but does that interfere with the original input?  
Even if not, with the output of the DAC still connected when the module is off (bypassed) the stuff (echo/loop) that is currently played will still be played and go into the output… I probably need to rethink my bypass switch! But if I disconnect the output of the DAC as well then I won’t have a “channel” for the LED… ☹

---

<div class="post-metadata">

**Author:** ![eric](https://avatars.discourse-cdn.com/v4/letter/e/898d66/32.png) [@eric](https://lookmumnocomputer.discourse.group/u/eric)\
**Post date:** [February 4, 2021, 8:33am UTC](https://lookmumnocomputer.discourse.group/t/kosmo-audiohacker-looking-for-mistakes-feedback/2374/23 "2021-02-04T08:33:13Z")

</div>

Usually a bypass is wired this way :

 ![Bypass](https://global.discourse-cdn.com/free1/uploads/lookmumnocomputer/original/2X/3/32547b27653a5ea8c684e0f463b50edb85b887a1.jpeg)  
You can obviously add the LED on the second half of the switch…

---

<div class="post-metadata">

**Author:** ![sebastian](https://yyz2.discourse-cdn.com/free1/user_avatar/lookmumnocomputer.discourse.group/sebastian/32/39_2.png) [@sebastian](https://lookmumnocomputer.discourse.group/u/sebastian)\
**Post date:** [February 4, 2021, 9:00am UTC](https://lookmumnocomputer.discourse.group/t/kosmo-audiohacker-looking-for-mistakes-feedback/2374/24 "2021-02-04T09:00:12Z")

</div>

Oh yes!! Why couldn’t I think of that?! I feel stupid again! XD thank you a lot! 🙂

---

<div class="post-metadata">

**Author:** ![Dud](https://yyz2.discourse-cdn.com/free1/user_avatar/lookmumnocomputer.discourse.group/dud/32/610_2.png) [@Dud](https://lookmumnocomputer.discourse.group/u/Dud)\
**Post date:** [February 4, 2021, 9:09am UTC](https://lookmumnocomputer.discourse.group/t/kosmo-audiohacker-looking-for-mistakes-feedback/2374/25 "2021-02-04T09:09:34Z")

</div>

But like this it’s not a “True bypass”, for that you need a DPDT (2x 3 pin)  
to deconnect completely input and output .

@fredrik shared this link in another thread

> **[True bypass wiring schemes – stinkfoot.se](http://stinkfoot.se/archives/2233)**

---

<div class="post-metadata">

**Author:** ![eric](https://avatars.discourse-cdn.com/v4/letter/e/898d66/32.png) [@eric](https://lookmumnocomputer.discourse.group/u/eric)\
**Post date:** [February 4, 2021, 9:12am UTC](https://lookmumnocomputer.discourse.group/t/kosmo-audiohacker-looking-for-mistakes-feedback/2374/26 "2021-02-04T09:12:11Z")

</div>

Yes, but with synth levels/impedances, it doesn’t matter if the IN jack stays connected to the electronics…  
It’s a whole other thing with guitar levels/impedances…

---

<div class="post-metadata">

**Author:** ![sebastian](https://yyz2.discourse-cdn.com/free1/user_avatar/lookmumnocomputer.discourse.group/sebastian/32/39_2.png) [@sebastian](https://lookmumnocomputer.discourse.group/u/sebastian)\
**Post date:** [June 30, 2021, 8:52pm UTC](https://lookmumnocomputer.discourse.group/t/kosmo-audiohacker-looking-for-mistakes-feedback/2374/27 "2021-06-30T20:52:40Z")

</div>

I made a few stupid mistakes, where I have the inputs of the opamps swapped, but apart from that it seems to be somewhat working as a bitcrusher at least!  
One very odd thing though: it only works if I boot the arduino not connected to the PCB (only with the usb cable between laptop and arduino). Then I can insert it into its socket and it works. If I just power on the PCB with arduino inserted (or press reset while its in the socket), it only does the `setup()` bit and then stops. I am running [this example](https://github.com/nootropicdesign/audio-hacker/blob/master/examples/DynamicSampleRate/DynamicSampleRate.ino) (I have some different pins, which I have adjusted in the audiohacker library).  
I think, it’s in line 81

```auto
  AudioHacker.writeDAC(playbackBuf);

```

at least, it does not get stuck if I comment that out.  
It might be in this `spiWrite` function, (which is called in `writeDAC`). There is a while loop which could be running forever, but I have no idea if that is what happens or why that happens and why it’s different if the arduino is on the PCB while it’s booting…

```auto
static inline __attribute__ ((always_inline)) byte spiWrite(byte data) {
  SPDR = data;
  while (!(SPSR & _BV(SPIF)));
  return SPDR;
}

```

Any ideas? What can I try?

---

<div class="post-metadata">

**Author:** ![sebastian](https://yyz2.discourse-cdn.com/free1/user_avatar/lookmumnocomputer.discourse.group/sebastian/32/39_2.png) [@sebastian](https://lookmumnocomputer.discourse.group/u/sebastian)\
**Post date:** [July 1, 2021, 8:54am UTC](https://lookmumnocomputer.discourse.group/t/kosmo-audiohacker-looking-for-mistakes-feedback/2374/28 "2021-07-01T08:54:17Z")

</div>

I found the [solution](https://forums.adafruit.com/viewtopic.php?f=24&t=15943)!!  
I have one of the switches connected to D10, which is the SS pin for SPI on the nano. When the switch pulls D10 to ground, the SPI transmission can not work. I have not yet understood why it works when the pin is pulled to ground after a few transmissions (when I insert the board later), but I am happy now. Only need to cut a trace again and use another input for the switch 🙂

---

<div class="post-metadata">

**Author:** ![sebastian](https://yyz2.discourse-cdn.com/free1/user_avatar/lookmumnocomputer.discourse.group/sebastian/32/39_2.png) [@sebastian](https://lookmumnocomputer.discourse.group/u/sebastian)\
**Post date:** [July 2, 2021, 9:58am UTC](https://lookmumnocomputer.discourse.group/t/kosmo-audiohacker-looking-for-mistakes-feedback/2374/29 "2021-07-02T09:58:12Z")

</div>

Okai, the hardware works now, I would say! 🙂  
Software also, kind of, but I need some help!  
What I did so far, is:

- always record the audio into the SRAM chip (if it’s full, start at address 0 again)
- if I press the button, stop recording and playback from the SRAM chip from current address (that means it starts the playback from the oldest “timestep” it has)
- I can change the sampling rate for recording and playback (I’m using the same for both), which changes the pitch if I do it during the playback and changes the possible length of the recording.

That’s quite cool already, but it’s not yet the effect that I am after! I would like it to be more like the 2hp freez, which Sam used here:

[![](https://global.discourse-cdn.com/free1/uploads/lookmumnocomputer/original/2X/0/0db4fcee9779508d97b0a9e7fecef0935e1503ba.jpeg "2HP FREEZ DUAL MACRO FREEZ SYNTH MODULE") ](https://www.youtube.com/watch?v=Zvyxk23MKA4)

How can I do that? I guess that one is more like a delay, which disconnects the input when you press the button?? so I have to add some kind of feedback from the output into the input and then change the length of the delay??? how?? I don’t really understand what’s going on there xD  
Does anybody know how to achieve this kind of effect?

---

<div class="post-metadata">

**Author:** ![sebastian](https://yyz2.discourse-cdn.com/free1/user_avatar/lookmumnocomputer.discourse.group/sebastian/32/39_2.png) [@sebastian](https://lookmumnocomputer.discourse.group/u/sebastian)\
**Post date:** [July 3, 2021, 10:13pm UTC](https://lookmumnocomputer.discourse.group/t/kosmo-audiohacker-looking-for-mistakes-feedback/2374/30 "2021-07-03T22:13:18Z")

</div>

Okay, some progress:

> **[Loopcrusher](https://hearthis.at/4p8iybld/loopcrusher/)**
>
> Listen to Loopcrusher by Strange Orbits on hearthis.at | Bass

I will write a bit more what I tried tomorrow 🙂

---

<div class="post-metadata">

**Author:** ![sebastian](https://yyz2.discourse-cdn.com/free1/user_avatar/lookmumnocomputer.discourse.group/sebastian/32/39_2.png) [@sebastian](https://lookmumnocomputer.discourse.group/u/sebastian)\
**Post date:** [July 6, 2021, 9:40pm UTC](https://lookmumnocomputer.discourse.group/t/kosmo-audiohacker-looking-for-mistakes-feedback/2374/31 "2021-07-06T21:40:54Z")

</div>

With video this time, because I added this shiny LED button 😉

https://player.vimeo.com/video/571842607

The logic is like this:  
if in record mode (default):  
record input to SRAM (circular buffer) and wait for button press  
on press: read potentiometer → loopLength. set current address (in buffer) as loop endpoint and currentAddress - loopLength as loop start (I have a bit of logic to cover for buffer wraparound, but not yet fully working), then go into playback mode!

playback mode:  
play the buffer from loop start point to loop end point, go to start point again  
read potentiometer and use that value to set the playback sample rate (that makes the sound speed up / slow down and change pitch).  
If button is released: go back to record mode, set sample rate back to default.

It works okay, but some issues: I can not go to very high pitches/ short repeats, because I can not get the sample rate higher than ~50kHz, if I do, the sound drops out, I think it’s Arduino limitation. How can I get faster playback then? skip samples? combine the sampling rate with skipping for faster? use a lower recording sample rate?  
The sample rate used in playback is absolute, so if I press the button the pitch instantly changes, I will set this to relative changes, I think.

I still like the 2hp freez more, but I still don’t really understand which parameters they change with the potentiometers. they also Any ideas what is happening there are welcome! I think they also change the playback sample rate once the button is pressed, because the pitch shifts when you turn the knob while button pressed, but then they also have the separate sample rate knob below… the manual says the upper knob is length/size and the lower one is sample rate. 🤔

Here’s the (very bad and uncleaned) code, if you’re interested:

```auto
#include <AudioHacker.h>

#define DEBUG
#define OFF 0
#define PASSTHROUGH 1
#define RECORD 2
#define PLAYBACK 3
#define RECORD_DONE 4

#define PLAY_BUTTON 8 // sebi
#define LED_BUTTON 3 // sebi

unsigned int playbackBuf = 2048;
unsigned int passthroughSampleRate;
unsigned int recordingSampleRate;
unsigned int playbackSampleRate;
unsigned int timer1Start;
volatile unsigned int timer1EndEven;
volatile unsigned int timer1EndOdd;

int currentA0Position;
volatile long address = 0;
volatile long endAddress = 0;
volatile byte addressChipNumber = 0;
volatile byte endAddressChipNumber = 0;

volatile long loopStartAddress = 0;
volatile long loopEndAddress = 0;
volatile boolean looparound = false;

volatile byte mode = RECORD; //SEBI
unsigned long lastDebugPrint = 0;
unsigned int readBuf[2];
unsigned int writeBuf;
boolean evenCycle = true;
unsigned int recordStartTime;
unsigned int recordEndTime;
boolean sampleRecorded = false;

unsigned int bufferLength = MAX_ADDR;

void setup() {
#ifdef DEBUG
  Serial.begin(115200); // connect to the serial port
#endif

  recordingSampleRate = DEFAULT_RECORDING_SAMPLE_RATE;
  passthroughSampleRate = DEFAULT_SAMPLE_RATE;
  passthroughSampleRate = DEFAULT_RECORDING_SAMPLE_RATE; // sebi
  timer1Start = UINT16_MAX - (F_CPU / passthroughSampleRate);

  pinMode(PLAY_BUTTON, INPUT);
  digitalWrite(PLAY_BUTTON, HIGH);

  pinMode(LED_BUTTON, OUTPUT);
  digitalWrite(LED_BUTTON, LOW);

  AudioHacker.begin();

#ifdef DEBUG
  Serial.print("sample rate = ");
  Serial.print(passthroughSampleRate);
  Serial.print(" Hz, recording sample rate = ");
  Serial.print(recordingSampleRate);
  Serial.print(" Hz");
  Serial.println();
#endif
}

void loop() {

#ifdef DEBUG
  if ((millis() - lastDebugPrint) >= 1000) {
    lastDebugPrint = millis();

// Serial.print("mode = ");
// Serial.println(mode);
// Serial.print(" bufferlength = ");
// Serial.println(bufferLength);
// Serial.print(" even cycles remaining = ");
// Serial.print(UINT16_MAX - timer1EndEven);
// Serial.print(" odd cycles remaining = ");
// Serial.print(UINT16_MAX - timer1EndOdd);
// Serial.println();
    if (((UINT16_MAX - timer1EndEven) < 20) || (((UINT16_MAX - timer1EndOdd) < 20))) {
      Serial.println("WARNING: ISR execution time is too long. Reduce sample rate or reduce the amount of code in the ISR.");
    }

  }
#endif

  // set sample rate
  //passthroughSampleRate = map(analogRead(1), 0, 1023, 1000, 60000);
  //passthroughSampleRate = passthroughSampleRate - (passthroughSampleRate % 100); // round to nearest 100 Hz

  // fixme
  //bufferLength = map(analogRead(0), 0, 1023, 1, MAX_ADDR);
  bufferLength = analogRead(0)*30;

  timer1Start = UINT16_MAX - (F_CPU / passthroughSampleRate);

  if (mode == RECORD) {
  
    // button was pressed, change to playback!!
    if (digitalRead(PLAY_BUTTON) == LOW) {
      Serial.println("button pressed, now in Playback mode");

      mode = PLAYBACK;
      loopStartAddress = address - bufferLength;
      loopEndAddress = address;
      if (loopStartAddress < 0) { // looped around!
        loopStartAddress += MAX_ADDR;
        looparound = true;
      }

      address = loopStartAddress; // start loop from beginning

      Serial.print("loopstartaddress: ");
      Serial.print(loopStartAddress);
      Serial.print(" loopendaddress: ");
      Serial.print(loopEndAddress);
      Serial.print(" looparound: ");
      Serial.print(looparound);

      Serial.println("");

      digitalWrite(LED_BUTTON, HIGH);
    }
  }

  if (mode == PLAYBACK) {

  // set sample rate
    passthroughSampleRate = map(analogRead(0), 0, 1023, 1000, 60000);
    passthroughSampleRate = passthroughSampleRate - (passthroughSampleRate % 100); // round to nearest 100 Hz
    timer1Start = UINT16_MAX - (F_CPU / passthroughSampleRate);

    
    if (digitalRead(PLAY_BUTTON) == HIGH) {
      // play button released
      mode = RECORD;
      //address = 0;
      digitalWrite(LED_BUTTON, LOW);
      //addressChipNumber = 0;

      // reset sample rate
      passthroughSampleRate = DEFAULT_RECORDING_SAMPLE_RATE;
      timer1Start = UINT16_MAX - (F_CPU / passthroughSampleRate);

    } 
  }
}

ISR(TIMER1_OVF_vect) {
  TCNT1 = timer1Start;
  unsigned int signal;

  AudioHacker.writeDAC(playbackBuf);

  if (mode == RECORD) {
    signal = AudioHacker.readADC();
    
    if (evenCycle) {
      // we only write to memory on odd cycles, so buffer the sampled signal.
      writeBuf = signal;
    } else {
      // Write two samples to SRAM
      AudioHacker.writeSRAMPacked(addressChipNumber, address, writeBuf, signal);

      address += 3;
      if (address > MAX_ADDR) {
       // Serial.println("addressfull during write!");
        address = 0;
      }
    }
  }

  if (mode == PLAYBACK) {
    if (evenCycle) {
      //long echoAddress = address - bufferLength;
      
      
      // Read from SRAM. Two 12-bit samples are read into readBuf[0] and readBuf[1].
      AudioHacker.readSRAMPacked(addressChipNumber, address, readBuf);
      signal = readBuf[0];

      address += 3;
      if (address > loopEndAddress && !looparound) {
          //Serial.println("addressfull!!");
          address = loopStartAddress;
      } else {
        if (address > MAX_ADDR) {
          address = 0;
          looparound = false;
        }
      }

    } else {
      signal = readBuf[1];
    }
  } // PLAYBACK

  playbackBuf = signal;

#ifdef DEBUG
  if (evenCycle) {
    timer1EndEven = TCNT1;
  } else {
    timer1EndOdd = TCNT1;
  }
#endif
  evenCycle = !evenCycle;
}

```

[Previous page](https://lookmumnocomputer.discourse.group/t/kosmo-audiohacker-looking-for-mistakes-feedback/2374.md?page=1)
