//Get data in degrees per seconds to rate vector [x,y,z] void Gyroscope::getData(float* rate) { cmr_read_rates(); //Read raw data to rawX, rawY and rawZ rate[0] = (parseRawData(rawX) - XOffset) * countsToDps; rate[1] = (parseRawData(rawY) - YOffset) * countsToDps; rate[2] = (parseRawData(rawZ) - ZOffset) * countsToDps; }
//Calibrate X, Y and Z offsets void Gyroscope::calibrate() { //Calculate mean of 1000 measurements in stable position for (int i = 0; i < 1000; i++) { cmr_read_rates(); //Read raw data XOffset += parseRawData(rawX) * 0.001f; YOffset += parseRawData(rawY) * 0.001f; ZOffset += parseRawData(rawZ) * 0.001f; delay(5); } Serial.print(XOffset); Serial.print(","); Serial.print(YOffset); Serial.print(","); Serial.println(ZOffset); }
/*************************************************************** * Function: Parser::parseNode() * Purpose : Parse an XML data node * Initial : Maxime Chevalier-Boisvert on October 20, 2008 **************************************************************** Revisions and bug fixes: */ Node* Parser::parseNode(const std::string& xmlString, size_t& charIndex, const PosVector& positions) { // If this is the beginning of a CDATA region if (tokenMatch(xmlString, charIndex, "<![CDATA[")) { // Parse the CDATA region return parseRawData(xmlString, charIndex, positions); } // If this is the beginning of an XML element else if (tokenMatch(xmlString, charIndex, "<")) { // Parse the XML element recursively return parseElement(xmlString, charIndex, positions); } // Otherwise, if this is a text region else { // Parse the text return parseText(xmlString, charIndex, positions); } }
bool KNMusicTagApev2::parseTag(QFile &musicFile, QDataStream &musicDataStream, KNMusicAnalysisItem &analysisItem) { //Check the file size first. if(musicFile.size()<APEv2HeaderSize) { return false; } //There're several positions we have to check: // * The beginning of the file. (APEv2) // * The end of the file. (APEv1, APEv2) // * If there's ID3v1 tag, check the position before ID3v1. (APEv1, APEv2) //Generate a header structure. APEHeader header; //Initial the tag start position. bool foundHeader=false; //Check the beginning of the file. if(checkHeader(0, musicDataStream, header)) { //Tag start right after the tag. So we don't need to move the position //of the data stream. //Set the header found flag. foundHeader=true; } //Check the end of the file. else if(checkHeader(musicFile.size()-APEv2HeaderSize, musicDataStream, header)) { //Move the data stream to the right position. It should be: (APEv1) //...........xxxx ... xxxxAPETAGEXxxxx ... xxx|(EOF) //(File data)| | | // Tag Start Header Start End of File //For APEv2, before the tag start it has another header. Ignore it. //Reset the device to start. musicDataStream.device()->reset(); //Skip the file data. musicDataStream.skipRawData(musicFile.size()-header.size); //Set the header found flag. foundHeader=true; } //Check the position before ID3v1. Some file may have both ID3v1 and APEv1/ //APEv2. else if(musicFile.size()>=ID3v1nAPEv2 && //File size first. checkHeader(musicFile.size()-ID3v1nAPEv2, musicDataStream, header)) { //Move the data stream to the right position. It should be: (APEv1) //...........xxxx ... xxxxAPETAGEXxxxx ... xxxTAGxxx ... xxx|(EOF) //(File data)| | | | // Tag Start Header Start ID3v1 End of File //For APEv2, before the tag start it has another header. Ignore it. //Reset the device to start. musicDataStream.device()->reset(); //Skip the file data. musicDataStream.skipRawData(musicFile.size()-ID3v1Size-header.size); //Set the header found flag. foundHeader=true; } //Check if we have found the header. If we didn't find any header, then //failed to parse the APEv1/APEv2. if(!foundHeader) { return false; } //Read the tag from the file. char *rawTagData=new char[header.size]; musicDataStream.readRawData(rawTagData, header.size); //Parse the raw tag data list. QList<APETagItem> tagList; parseRawData(rawTagData, header, tagList); //Recover the memory. delete[] rawTagData; //Write the tag list to analysis item. //Get the detail info. KNMusicDetailInfo &detailInfo=analysisItem.detailInfo; //Parse each tag list. for(auto i=tagList.constBegin(); i!=tagList.constEnd(); ++i) { //Get the frame index from the hash list. int frameIndex=m_keyIndex.value((*i).key, -1); //If we cannot map the key to the index, then ignore the current frame. if(frameIndex==-1) { continue; } switch(frameIndex) { case TrackNumber: { //Get the track string data. QString trackText=QString((*i).value); //Find the '/' char. int splitterIndex=trackText.indexOf('/'); //If we cannot find the splitter, if(splitterIndex==-1) { //means it only contains track number. detailInfo.textLists[TrackNumber]=QVariant(trackText); } else { //Or else, it contains track number and track count data. //Treat the left side as track number, and the right side as //track count. detailInfo.textLists[TrackNumber]=trackText.left(splitterIndex); detailInfo.textLists[TrackCount]=trackText.mid(splitterIndex+1); } } default: //For default cases, because it's UTF-8 plain text, just write the //data to the text list. detailInfo.textLists[frameIndex]=QString((*i).value); } } //Parse complete. return true; }
bool KNMusicTagApev2::writeTag(const KNMusicAnalysisItem &analysisItem) { //Write the data according to the detail info. const KNMusicDetailInfo &detailInfo=analysisItem.detailInfo; //Check the file is still exist or not. QFile musicFile(detailInfo.filePath); //If the file is not exist then return false. if(!musicFile.exists()) { return false; } //Find the original tag data. //ID3v1 header flag. bool hasId3v1=false; //Generate a header structure. APEHeader header; //Generate the raw tag data list. QList<APETagItem> itemList; //Initial the tag start position. qint64 tagDataStart=-1, tagDataLength=-1; //Open the file first. if(musicFile.open(QIODevice::ReadOnly)) { //Generate a data stream. QDataStream musicDataStream(&musicFile); if(musicFile.size() > 128) { //ID3v1 header cache. char id3v1Header[3]; //Check whether there's ID3v1 tag in the music file. musicDataStream.skipRawData(musicFile.size()-128); //Read ID3v1 header. musicDataStream.readRawData(id3v1Header, 3); //Check the header, and we can know that whether there's ID3v1 //header. hasId3v1=(id3v1Header[0]=='T' && id3v1Header[1]=='A' && id3v1Header[2]=='G'); } //Check the beginning of the file. if(checkHeader(0, musicDataStream, header)) { //Set the tag data start. tagDataStart=0; //Set the tag length to header length. tagDataLength=header.size; //Check whether is a footer in the tag. if(header.size > APEv2HeaderSize) { //Check the footer. APEHeader footer; //Tried to parse the footer. if(checkHeader(header.size, musicDataStream, footer)) { //Update the tag length. tagDataLength+=APEv2HeaderSize; } } //Reset the device to start. musicDataStream.device()->reset(); //Skip the file data. musicDataStream.skipRawData(APEv2HeaderSize); } //Check the end of the file. else if(checkHeader(musicFile.size()-APEv2HeaderSize, musicDataStream, header)) { //Save the tag start data. int tagContentStart=musicFile.size()-header.size; //Check the footer. APEHeader footer; //Check whether there's a header in the tag. if(checkHeader(tagContentStart-APEv2HeaderSize, musicDataStream, footer)) { //Save the tag data start position as the header start position. //This is APEv2 tag. tagDataStart=tagContentStart-APEv2HeaderSize; //The tag length will be a header size + tag size. tagDataLength=APEv2HeaderSize + header.size; } else { //This is APEv1 tag. tagDataStart=tagContentStart; //The tag length will be tag size. tagDataLength=header.size; } //Reset the device to start. musicDataStream.device()->reset(); //Skip the file data. musicDataStream.skipRawData(tagContentStart); } //Check the position before ID3v1. Some file may have both ID3v1 and //APEv1/APEv2. else if(musicFile.size()>=(ID3v1nAPEv2 + APEv2HeaderSize) && //File size first. checkHeader(musicFile.size()-ID3v1nAPEv2, musicDataStream, header)) { //Save the tag start position. int tagContentStart=musicFile.size()-ID3v1Size-header.size; //Check the footer. APEHeader footer; //Check whether there's a header in the tag. if(checkHeader(tagContentStart-APEv2HeaderSize, musicDataStream, footer)) { //Save the tag data start position as the header start position. //This is APEv2 tag. tagDataStart=tagContentStart-APEv2HeaderSize; //The tag length will be a header size + tag size. tagDataLength=APEv2HeaderSize + header.size; } else { //This is APEv1 tag. tagDataStart=tagContentStart; //The tag length will be tag size. tagDataLength=header.size; } //Reset the device to start. musicDataStream.device()->reset(); //Skip the file data. musicDataStream.skipRawData(tagContentStart); } //Parse the data if we find the header. if(tagDataStart!=-1) { //Read the tag from the file. char *rawTagData=new char[header.size]; musicDataStream.readRawData(rawTagData, header.size); //Parse the raw tag data list. parseRawData(rawTagData, header, itemList); //Recover the memory. delete[] rawTagData; } //Close the music file. musicFile.close(); } //Add all the text labels to detail frames if it's not empty. for(int i=0; i<MusicDataCount; i++) { //Check if the text is empty. if(detailInfo.textLists[i].toString().isEmpty()) { continue; } //Get the frame key from hash group. QString key=m_indexKey.value(i, QString()); //If the key is empty, means you cannot write this data to APEv2. if(key.isEmpty()) { continue; } //Generate a data frame. APETagItem item; //Save the key. item.key=key; //According to the frame, generate the item. switch(i) { case DiscNumber: //If disc count isn't empty, then add disc count to disc number //data. item.value=detailInfo.textLists[DiscCount].toString().isEmpty()? detailInfo.textLists[DiscNumber].toString().toUtf8(): (detailInfo.textLists[DiscNumber].toString()+"/"+ detailInfo.textLists[DiscCount].toString()).toUtf8(); default: //Add the whole data to the item. item.value=detailInfo.textLists[i].toString().toUtf8(); } //Remove the all the original item. //We have to check the key from the back to the first, and we won't get //mess to the index. for(int i=itemList.size()-1; i>-1; i--) { //If the key is the same as current key, if(itemList.at(i).key==key) { //Remove it. itemList.removeAt(i); } } //Add current key to item list. itemList.append(item); } //Now translate the frame structure data to the raw data. QByteArray contentData; //Prepare the cache size. char numberCache[4]; //Simply transfered the APETagItem to content data. for(auto i=itemList.constBegin(); i!=itemList.constEnd(); ++i) { //Get the item size. quint32 size=(*i).value.size(); //First transfer item size to raw data into cache. numberToData(size, numberCache); //Add item size to content data. contentData.append(numberCache, 4); //Transfer the flag to raw data into cache. numberToData((*i).flag, numberCache); //Add flag data to content data. contentData.append(numberCache, 4); //Add item key to content data. contentData.append((*i).key.toUtf8()); //Add 0x00 for item key terminator. contentData.append('\0'); //Add item value. contentData.append((*i).value); } //Update the header data. header.size=contentData.size()+32; header.itemCount=itemList.size(); //We will write the APEv2 data to the end part of the file. Just before the //ID3v1. //Check the header data. //Open the music file again. if(!musicFile.open(QIODevice::ReadOnly)) { return false; } //Generate a temporary file, write the new data to the temporary file. QTemporaryFile updatedTagFile; //Open the temporary file, if we cannot open the temporary file it will be //failed to write the tag. if(!updatedTagFile.open()) { //Close the opened music file. musicFile.close(); return false; } //Initial the file size. qint64 dataSurplusSize=musicFile.size(); /* * Algorithm: * We treat the file as these two kinds of format: * APEv2 | xxxx (Content) (| ID3v1) * or * xxxx (Content) | APEv2 (| ID3v1) * So we have to process the ID3v1 at first. Then the file should be like * the following: * APEv2 | xxxx (Content) * or * xxxx (Content) | APEv2 * And now, we only have to check if the APEv2 is at the beginning or the * end of the content. */ //If we have ID3v1, then remove the tag from the copying bytes. if(hasId3v1) { //Reduce the ID3v1 tag size. dataSurplusSize-=128; } //Check whether we have original APEv2 header. if(tagDataStart!=-1) { //Reduce the tag size from the file size. dataSurplusSize-=tagDataLength; //Check whether the header is at the start of the music file. if(tagDataStart==0) { //It's at the beginning of the file. //Skip the Original APEv2 tag at the beginning of the file. musicFile.seek(tagDataLength); } } //Generate the music data cache. char *turboCache=new char[DataCacheSize]; int bytesRead; //Now copy all the content from the original file to temporary file. while(dataSurplusSize>0) { //Read the original data. bytesRead=musicFile.read(turboCache, (DataCacheSize < dataSurplusSize ? DataCacheSize : dataSurplusSize)); //Write the cache to temporary file. updatedTagFile.write(turboCache, bytesRead); //Reduce the surplus size. dataSurplusSize-=bytesRead; } //According to the hydrogenaud.io, we have to put the APEv2 at the end of //the file. //Write new APEv2 tag to the file. /* * From http://wiki.hydrogenaud.io/index.php?title=Ape_Tags_Flags: * Bit 29: * 0: This is the footer, not the header * 1: This is the header, not the footer */ //First set the item flag to header in header data bytearray. updatedTagFile.write(generateHeaderData(header, true)); //Then, write the content data. updatedTagFile.write(contentData); //Last, write the footer data. updatedTagFile.write(generateHeaderData(header, false)); //If there's ID3v1 tag, then copy the ID3v1 data from the original file. if(hasId3v1) { //Seek to the ID3v1 tag start. musicFile.seek(musicFile.size()-128); //Read 128 bytes ID3v1 tag. musicFile.read(turboCache, 128); //Write the cache to temporary file. updatedTagFile.write(turboCache, 128); } //Close the music file. musicFile.close(); //Reset the temporary file. updatedTagFile.reset(); //Reopen the music file as write only mode, write all the udpated tag file //data to the music file. if(!musicFile.open(QIODevice::WriteOnly)) { return false; } //Copy data from temporary file to music file. bytesRead=updatedTagFile.read(turboCache, DataCacheSize); while(bytesRead>0) { //Write the cache to music file. musicFile.write(turboCache, bytesRead); //Read new data from the original file to cache. bytesRead=updatedTagFile.read(turboCache, DataCacheSize); } //Close the music file and temporary file. musicFile.close(); updatedTagFile.close(); //Clear up the turbo cache. delete[] turboCache; //The tag rewrite is finished. return true; }
void Magnetometer::getData(float* magnetodata) { hmc_read_rates(); magnetodata[0] = parseRawData(magX); magnetodata[1] = parseRawData(magY); magnetodata[2] = parseRawData(magZ); }