Ардуино - запись звука

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
olegue
Собутыльник Кота
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Re: Ардуино - запись звука

Сообщение olegue »

if (recByteCount % 1024 == 512 && recPressed == 1) {
rec.write(buf00, 512); // save buf01 to card
recByteSaved += 512;
}
if (recByteCount % 1024 == 0 && recPressed == 1) {
rec.write(buf01, 512); // save buf02 to card
recByteSaved += 512;
}

а зачем нужно два буфера, прокоменнтируйте код.

Добавлено after 15 minutes 40 seconds:
Типа попеременная запись, пишем в один, потом сбрасываем на карту, а пока сбразываем пишем во вторрой. Так что оли?
Morroc
Друг Кота
Сообщения: 19495
Зарегистрирован: Чт фев 20, 2014 18:57:55

Re: Ардуино - запись звука

Сообщение Morroc »

Так
"Вся военная пропаганда, все крики, ложь и ненависть исходят от людей, которые на эту войну не пойдут !" / Джордж Оруэлл /
"Война - это,когда за интересы других,гибнут совершенно безвинные люди." / Уинстон Черчилль /
roman.com
Друг Кота
Сообщения: 9147
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

Re: Ардуино - запись звука

Сообщение roman.com »

открой код... глянь..)) отсюда не видно))

обновились))
2.jpg
(74.1 КБ) 49 скачиваний
надо ещё видео добавить...
и сделать IP телефон на меги328... )) с WEB-камерой ))
:tea:
Аватара пользователя
olegue
Собутыльник Кота
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Re: Ардуино - запись звука

Сообщение olegue »

Ну Если взять атмегу8 и отдавать 1к памяти на 2буфера по 512, то какой смысл тогда в этом.
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Ардуино - запись звука

Сообщение Dimon456 »

olegue писал(а):то какой смысл тогда в этом.
Код в студию.
roman.com
Друг Кота
Сообщения: 9147
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

Re: Ардуино - запись звука

Сообщение roman.com »

а нет никакого смысла))))
сама Ардуина... в нашем мире... не имеет ни какого смысла...
:))
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Ардуино - запись звука

Сообщение Dimon456 »

Все имеет смысл.
Последний раз редактировалось Dimon456 Вт июн 07, 2022 21:51:05, всего редактировалось 1 раз.
roman.com
Друг Кота
Сообщения: 9147
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

Re: Ардуино - запись звука

Сообщение roman.com »

выше писал...
только вещи... несущие пользу людям... имеют смысл))
:tea:
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Ардуино - запись звука

Сообщение Dimon456 »

А разве тебе неинтересно, вдруг его изобретение превратится в вещь несущую пользу людям?
Morroc
Друг Кота
Сообщения: 19495
Зарегистрирован: Чт фев 20, 2014 18:57:55

Re: Ардуино - запись звука

Сообщение Morroc »

А его изобретениие непременно на меге8 нужно изобретать ? )
"Вся военная пропаганда, все крики, ложь и ненависть исходят от людей, которые на эту войну не пойдут !" / Джордж Оруэлл /
"Война - это,когда за интересы других,гибнут совершенно безвинные люди." / Уинстон Черчилль /
Аватара пользователя
olegue
Собутыльник Кота
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Re: Ардуино - запись звука

Сообщение olegue »

Morroc писал(а):А его изобретениие непременно на меге8 нужно изобретать ? )
Мега8 есть в наличии (прислал кто-то из форумачан, еще раз спасибо огромное), поэтому вот и изобретаю на чем есть. Ну пока изобретаю на Ардуине. Не совсем правда на оригинально, просто взял Атмегу 328 поставил кварц , прошил загрузчик , ну и так далее.


Короче, ПОБЕДА! Взлетело. Файлы именованы по часам через ролбэк функцию

Код: Выделить всё

void dateTime(uint16_t* date, uint16_t* time) {
  DateTime now = rtc.now();

  // return date using FAT_DATE macro to format fields
  *date = FAT_DATE(now.year(), now.month(), now.day());

  // return time using FAT_TIME macro to format fields
  *time = FAT_TIME(now.hour(), now.minute(), now.second());
}

Код: Выделить всё

void loop(void)
{

  //Other code that does stuff

  //put this next line *Right Before* any file open line:
  SdFile::dateTimeCallback(dateTime);
  dataFile = SD.open(datafilename, FILE_WRITE);

  //other code that does stuff

}
взято отсюда https://forum.arduino.cc/t/file-creatio ... d/336037/2

при размере буфера 2 по 512 запись не начиналась, так как памяти sram всего 58байт оставалось
сделать размер буфера 2 по 386, наверно можно было и 2 по 400 поставить. Осталось памяти 307байт
Немного ускорееном темпе идет звук, можно еще отвоевать для буфера памяти, нужно поэкспериментировать


Проблема была в том что Забыл прописать rts.begin(). Вот и мучался сутки. Но это уже в прошлом.
Dimon456 писал(а):А разве тебе неинтересно, вдруг его изобретение превратится в вещь несущую пользу людям?
эта штука уже принесла мне пользу. Так как с плеч свалился огромный головняк.
roman.com писал(а):сама Ардуина... в нашем мире... не имеет ни какого смысла..
Ваши посты про мегу уже активно перечитываю. Приложенные файлы просматриваю и анализирую.
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Re: Ардуино - запись звука

Сообщение Ivanoff-iv »

можно заявить стерео (или 16 бит запись) но данные передавать или по 2 раза одинаковые или через байт слать 0, тогда буфера потребуются не по 512, а по 256 байт.
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Аватара пользователя
olegue
Собутыльник Кота
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Re: Ардуино - запись звука

Сообщение olegue »

запись хоть и удовлтворитльная но какая-то рваная получилась. Надо поправить что бы буфер был 256, но качство вернуть. Распечатал код , пытаюсь разобраться.

Я так понимаю, что когда я уменьшил буфер, то на карту в сектор 512байт записываются пустые значения, что в итоге влияет на проигрывание

Ivanoff-iv,
можно заявить стерео (или 16 бит запись) но данные передавать или по 2 раза одинаковые или через байт слать 0, тогда буфера потребуются не по 512, а по 256 байт.
ну вот в этом месте мне совсем не хватает компетенции, буду разбираться
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Ардуино - запись звука

Сообщение Dimon456 »

Ivanoff-iv писал(а):тогда буфера потребуются не по 512, а по 256 байт.
К сожалению его кода не видно.
Но думаю, раз запись звука значит используется АЦП, а раз АЦП значит можно запись на флеш-карту объединить с АЦП и один буфер в 512 байт вообще исключить.

Ну а далее посмотреть откуда там 15кило программного кода взялось, ну хоть не в 8 мегу но по крайне мере в 168 утрамбовать вместе с ардуиновским загрузчиком.
roman.com
Друг Кота
Сообщения: 9147
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

Re: Ардуино - запись звука

Сообщение roman.com »

olegue писал(а):ну вот в этом месте мне совсем не хватает компетенции, буду разбираться
что тут разбираться))

выше писал...
wav формат поддерживает разные форматы записи... и разный битрейт...
8 бит, моно/ стерео.
16 бит, моно/стерео.

но в конкретно нашем случае (с Ардуино) всё это не имеет значение... Буфер 512 надо писать целиком. )) Потому что так работает библиотека Ардуино)) А как именно работает библиотека Ардуино... мы так и не разобрались...
:tea:
--------------
8 бит, моно. (один канал - 00000000)
00000000
00000000
00000000
...
всего 512 байт.
--------------
8 бит, стерео. (левый канал - 00000000, правый канал - 00000000)
00000000 00000000
00000000 00000000
00000000 00000000
...
всего 512 байт.
--------------
16 бит, моно. (один канал - 00000000 00000000)
00000000 00000000
00000000 00000000
00000000 00000000
...
всего 512 байт.
--------------
16 бит, стерео. (левый канал - 0000000 000000000, правый канал - 00000000 000000000)
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000
...
всего 512 байт.
--------------
и т.д.
:)

я пишу на ПК )) wav формат я переключаю кнопочками))
а так же меняю битрейт... 8000,11025,16000,22050,44100...
причём всё переключается "на ходу"... без остановки записи))

а буфер для записи я выбираю сам...
можно писать весь wav файл целиком...
а можно писать wav файл по одному байту...
2.jpg
(84.78 КБ) 45 скачиваний
на самом деле программа на ПК и программа в Ардуино ничем не отличается))
принцип работы везде одинаковый))
:tea:
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Re: Ардуино - запись звука

Сообщение Ivanoff-iv »

сделать массив чар[256] а на отправку отправлять инт переменную... 256 интов как-раз будут 512 байт.
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Аватара пользователя
olegue
Собутыльник Кота
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Re: Ардуино - запись звука

Сообщение olegue »

Dimon456,
Dimon456 писал(а):К сожалению его кода не видно.
без проблема. Вот код фактически что счас есть буфер 512 байт заменен на 386 для освобождения памяти
в коде где было 512 заменил на 386. Остальное не трогал, в части где касается сэмплирования и сброса на карту.
Спойлер

Код: Выделить всё

 // Arduino Audio Recorder 


#include <SdFat.h> // https://yadi.sk/d/zqi8-L5xruhFq
#include <EEPROM.h>

#include <RTClib.h>

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

SdFat sd;
SdFile rec;
RTC_DS1307 rtc;

const int chipSelect = 4; /* Поменял на 10-pln */
unsigned long fileSize = 0L;
unsigned long waveChunk = 16;
unsigned int waveType = 1;
unsigned int numChannels = 1;
unsigned long sampleRate = 22050;
unsigned long bytesPerSec = 22050;
unsigned int blockAlign = 1;
unsigned int bitsPerSample = 8;
unsigned long dataSize = 0L;
unsigned long recByteCount = 0L;
unsigned long recByteSaved = 0L;
const int btnStart = 6;
const int btnStop = 5;
const int ledStart = 2;
const int ledStop = 3;
int recPressed = 0;
int stopPressed = 0;
unsigned long oldTime = 0L;
unsigned long newTime = 0L;
byte buf00[386]; // buffer array 1
byte buf01[386]; // buffer array 2
byte byte1, byte2, byte3, byte4;
unsigned int bufByteCount;
byte bufWrite;

unsigned long timer1;
int timer1on = 0;
//----------------------------------------------------
//char NameRecord[4]; /* Имя нового - записываемого файла на SD-карту. */
int RecordNumber; /* Номер записи - храним в EEPROM. в диапазоне 0..255. */
char filename[12]; 

void setup() { // THIS RUNS ONCE
  rtc.begin();
//EEPROM.put(0, 20000);
  Setup_timer2();
  Setup_ADC();

  pinMode(10, OUTPUT);
  pinMode(ledStart, OUTPUT);
  pinMode(ledStop, OUTPUT);
  pinMode(btnStop, INPUT_PULLUP);
  pinMode(btnStart, INPUT_PULLUP);

  if (sd.begin(chipSelect, SPI_FULL_SPEED)) { // initialise card on SPI to 8MHz SPI bus speed
    for (int dloop = 0; dloop < 4; dloop++) {
      digitalWrite(ledStart, !digitalRead(ledStart));
      delay(100);
    }
  } else { // if error, flash LED twice per second, until reset
    while (1) {
      digitalWrite(ledStart, !digitalRead(ledStart));
      delay(500);
    }
  }

}

void loop() { // THIS RUNS LOTS!

 if (digitalRead(btnStart) == LOW && recPressed == 0) {
    /* Записываем в RecordNumber, значение из ячейки №0 EEPROM, и прибавляем 1. */
    /*RecordNumber = EEPROM.read(0) + 1;*/
     if (RecordNumber == 32767)RecordNumber = 0;
/*RecordNumber==RecordNumber+1;*/
       EEPROM.get(0,RecordNumber) ;
       /* Записываем в ячейку №0 EEPROM, увеличенное значение RecordNumber. */
    /*EEPROM.write(0, RecordNumber);*/
    EEPROM.put(0, RecordNumber+1);
   String str;  //declaring string.
    //
   str = String(RecordNumber); //converting integer into a string.
   while (str.length() < 6)
    {
    str = "0" + str;
      }
   str.concat(".wav");
   str.toCharArray(filename, sizeof(filename));
    /*str.toCharArray(NameRecord, 4); //passing the value of the string to the character array.*/
    /*SdFile::dateTimeCallback(dateTime);*/
    StartRec(); // launch StartRec method
    timer1on = 0;
  }
  else if (digitalRead(btnStart) == HIGH && recPressed == 1 && timer1on == 0)
    {
      timer1 = millis();
      timer1on = 1;
    }
    else if (digitalRead(btnStart) == LOW && recPressed == 1 && timer1on == 1) {
    timer1on = 0; 
    }
   
  else if (digitalRead(btnStart) == HIGH && recPressed == 1 && timer1on == 1 && (millis() - timer1) > 2000)
  {
    StopRec(); // launch StopRec method
    
    /*         Поэтому (Делаем программную перезагрузку). */
    ((void (*)())0x0000)(); /* Делаем программную перезагрузку - Arduino */
  }
 
  if (recByteCount % 1024 == 386 && recPressed == 1) {
    rec.write(buf00, 386);  // save buf01 to card
    recByteSaved += 386;
  }
  if (recByteCount % 1024 == 0 && recPressed == 1) {
    rec.write(buf01, 386);  // save buf02 to card
    recByteSaved += 386;
  }
}

void StartRec() { // begin recording process

  digitalWrite(ledStart, HIGH);
  digitalWrite(ledStop, LOW);
  recByteCount = 0;
  recByteSaved = 0;
  recPressed = 1; // recording button has been pressed
  stopPressed = 0;
  writeWavHeader();
  sbi (TIMSK2, OCIE2A); // enable timer interrupt, start grabbing audio

}

void StopRec() { // stop recording process, update WAV header, close file

  cbi (TIMSK2, OCIE2A); // disable timer interrupt
  writeOutHeader();
  digitalWrite(ledStart, LOW); // turn off recording LED
  digitalWrite(ledStop, HIGH); // light stop LED
  recPressed = 0;

}

void writeOutHeader() { // update WAV header with final filesize/datasize

  rec.seekSet(4);
  byte1 = recByteSaved & 0xff;
  byte2 = (recByteSaved >> 8) & 0xff;
  byte3 = (recByteSaved >> 16) & 0xff;
  byte4 = (recByteSaved >> 24) & 0xff;
  rec.write(byte1);  rec.write(byte2);  rec.write(byte3);  rec.write(byte4);
  rec.seekSet(40);
  rec.write(byte1);  rec.write(byte2);  rec.write(byte3);  rec.write(byte4);
  rec.close();

}

void dateTime(uint16_t* date, uint16_t* time) {
  DateTime now = rtc.now();

  // return date using FAT_DATE macro to format fields
  *date = FAT_DATE(now.year(), now.month(), now.day());

  // return time using FAT_TIME macro to format fields
  *time = FAT_TIME(now.hour(), now.minute(), now.second());
}

void writeWavHeader() { // write out original WAV header to file

  recByteSaved = 0;
  // rec.open("rec00000.wav", O_CREAT | O_TRUNC | O_RDWR);
  /*rec.open(NameRecord, O_CREAT | O_TRUNC | O_RDWR); /* Имя нового - записываемого файла на SD-карту. */
  //DateTime now = rtc.now();
   SdFile::dateTimeCallback(dateTime);
   rec.open(filename, O_CREAT | O_TRUNC | O_RDWR); /* Имя нового - записываемого файла на SD-карту. */
   //rec.timestamp(T_CREATE, now.year(), now.month(), now.day(), now.hour(), now.minute(), now.second());
  rec.write("RIFF");
  byte1 = fileSize & 0xff;
  byte2 = (fileSize >> 8) & 0xff;
  byte3 = (fileSize >> 16) & 0xff;
  byte4 = (fileSize >> 24) & 0xff;
  rec.write(byte1);  rec.write(byte2);  rec.write(byte3);  rec.write(byte4);
  rec.write("WAVE");
  rec.write("fmt ");
  byte1 = waveChunk & 0xff;
  byte2 = (waveChunk >> 8) & 0xff;
  byte3 = (waveChunk >> 16) & 0xff;
  byte4 = (waveChunk >> 24) & 0xff;
  rec.write(byte1);  rec.write(byte2);  rec.write(byte3);  rec.write(byte4);
  byte1 = waveType & 0xff;
  byte2 = (waveType >> 8) & 0xff;
  rec.write(byte1);  rec.write(byte2);
  byte1 = numChannels & 0xff;
  byte2 = (numChannels >> 8) & 0xff;
  rec.write(byte1);  rec.write(byte2);
  byte1 = sampleRate & 0xff;
  byte2 = (sampleRate >> 8) & 0xff;
  byte3 = (sampleRate >> 16) & 0xff;
  byte4 = (sampleRate >> 24) & 0xff;
  rec.write(byte1);  rec.write(byte2);  rec.write(byte3);  rec.write(byte4);
  byte1 = bytesPerSec & 0xff;
  byte2 = (bytesPerSec >> 8) & 0xff;
  byte3 = (bytesPerSec >> 16) & 0xff;
  byte4 = (bytesPerSec >> 24) & 0xff;
  rec.write(byte1);  rec.write(byte2);  rec.write(byte3);  rec.write(byte4);
  byte1 = blockAlign & 0xff;
  byte2 = (blockAlign >> 8) & 0xff;
  rec.write(byte1);  rec.write(byte2);
  byte1 = bitsPerSample & 0xff;
  byte2 = (bitsPerSample >> 8) & 0xff;
  rec.write(byte1);  rec.write(byte2);
  rec.write("data");
  byte1 = dataSize & 0xff;
  byte2 = (dataSize >> 8) & 0xff;
  byte3 = (dataSize >> 16) & 0xff;
  byte4 = (dataSize >> 24) & 0xff;
  rec.write(byte1);  rec.write(byte2);  rec.write(byte3);  rec.write(byte4);

}

void Setup_timer2() {

  TCCR2B = _BV(CS21);  // Timer2 Clock Prescaler to : 8
  TCCR2A = _BV(WGM21); // Interupt frequency  = 16MHz / (8 x 90 + 1) = 22191Hz
  OCR2A = 90; // Compare Match register set to 90

}

void Setup_ADC() {

  ADMUX = 0x61; // set ADC to read pin A5, ADLAR to 1 (left adjust)
  cbi(ADCSRA, ADPS2); // set prescaler to 8 / ADC clock = 2MHz
  sbi(ADCSRA, ADPS1);
  sbi(ADCSRA, ADPS0);
}

ISR(TIMER2_COMPA_vect) {

  sbi(ADCSRA, ADSC); // start ADC sample
  while (bit_is_set(ADCSRA, ADSC)); // wait until ADSC bit goes low = new sample ready
  recByteCount++; // increment sample counter
  bufByteCount++;
  if (bufByteCount == 386 && bufWrite == 0) {
    bufByteCount = 0;
    bufWrite = 1;
  } else if (bufByteCount == 386 & bufWrite == 1) {
    bufByteCount = 0;
    bufWrite = 0;
  }

  if (bufWrite == 0) {
    buf00[bufByteCount] = ADCH;
  }
  if (bufWrite == 1) {
    buf01[bufByteCount] = ADCH;
  }


  //  if (recByteCount % 1024 < 386) { // determine which buffer to store sample into
  //    buf01[recByteCount % 386] = ADCH;
  //  } else {
  //    buf02[recByteCount % 386 ] = ADCH;
  //  }

}

Код: Выделить всё

Скетч использует 16214 байт (50%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 1745 байт (85%) динамической памяти, оставляя 303 байт для локальных переменных. Максимум: 2048 байт.
Недостаточно памяти, программа может работать нестабильно.
Добавлено after 8 minutes 23 seconds:
roman.com,
Потому что так работает библиотека Ардуино)) А как именно работает библиотека Ардуино... мы так и не разобрались...
которая библиотека? sdfat? Библиотека работы с картой?
Morroc
Друг Кота
Сообщения: 19495
Зарегистрирован: Чт фев 20, 2014 18:57:55

Re: Ардуино - запись звука

Сообщение Morroc »

Да, она. Она же вроде секторами пишет.
"Вся военная пропаганда, все крики, ложь и ненависть исходят от людей, которые на эту войну не пойдут !" / Джордж Оруэлл /
"Война - это,когда за интересы других,гибнут совершенно безвинные люди." / Уинстон Черчилль /
Аватара пользователя
olegue
Собутыльник Кота
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Re: Ардуино - запись звука

Сообщение olegue »

400 байт поставил буфера. 450 - уже не работает.

Добавлено after 2 minutes 52 seconds:
roman.com писал(а):на самом деле программа на ПК и программа в Ардуино ничем не отличается))
принцип работы везде одинаковый))
:tea:
и это именно то что я нифига пока не понимаю

Добавлено after 1 minute 22 seconds:
пробовал что-то искать на ютубе что бы популярно объяснили эту тему. У канала Narod stream есть хороший ролик как зарядить sd card под Atmega8, но его просмотр пока не дал нужного результата.

Добавлено after 1 minute 57 seconds:
было бы неплохо если бы ко-то подробно прокоментировал строки из моего кода , касающиеся накопления байт в буфере и сброса их на карту. Тогда бы у меня появилось хоть какое то представления на нужном мне примере.
Morroc
Друг Кота
Сообщения: 19495
Зарегистрирован: Чт фев 20, 2014 18:57:55

Re: Ардуино - запись звука

Сообщение Morroc »

Это как принцип рыбалки. "Чего там уметь - наливай да пей" :) Если бы библиотеке ардуины можно было скормить поток данных и пофиг как она его там пишет в фоне, то и тут проблемы не было бы.

[uquote="olegue",url="/forum/viewtopic.php?p=4242446#p4242446"]подробно прокоментировал строки из моего кода , касающиеся накопления байт в буфере и сброса их на карту[/uquote]
Куда подробнее еще... в один буфер пишем байты с ацп в прерывании вроде как, другой буфер в это время пишем на карту, потом меняем местами
"Вся военная пропаганда, все крики, ложь и ненависть исходят от людей, которые на эту войну не пойдут !" / Джордж Оруэлл /
"Война - это,когда за интересы других,гибнут совершенно безвинные люди." / Уинстон Черчилль /
Ответить

Вернуться в «AVR»