- 환경변수 설정
1) 시스템 변수
변수이름 : JAVA_HOME
변수 값 : C:\jdk1.5.0_05

2) 사용자 변수
변수이름 : classpath
변수 값 : .;%JAVA_HOME%\lib\tools.jar

- 확인
1) cmd.exe 실행 후 JAVA_HOME dir말고 다른 위치로 이동.
2) set classpath
> CLASSPATH=.;C:\jdk1.5.0_05\lib\tools.jar
이렇게 나오면 성공.

- 테스트 코드 (Hello.java)
public class Hello{
   public static void main(String args[]){
       System.out.println("안녕");
   }
}


- 컴파일/실행
> javac Hello.java
> java Hello

12월1일부터 ~ 2월15일까지 취업활동을 시작해서.. 이번에 취업을 하게 된 사람입니다..구직활동을 하면서 느꼇던 취업란 실감과.. 그외 몇가지 취업 도움이 되고자 글을 적습니다.. 

180 군데 이력서를 넣었고.. 12 군데의 면접을 봤고.. 총 3군데 합격을 했습니다.

( 130 군데 이력서를 넣을땐.. 2군데 면접을 보았고.. 포트폴리오 첨부후.. 10 군데 정도 보았습니다. ) 

제 소개를 하자면.. 27 살이구.. 04년도 초대졸 전공졸업자에.. 3년간 공백과.. 08년도11월 JAVA JSP 학원수료자 였습니다.

공고생졸업에.. 초대졸에.. 제2외국어.. 토익 어학연수 이런거 없구.. IT 아르바이트 경험 인턴 이런거 없구.. 학교두 빨리 졸업해서.. 3년간의 공백기간이 있습니다 (불이익당함) 근데 딱 3가지만.. 있습니다.. 학원수료 / 포트폴리오 / 자격증 

1. 이력서..

개인 이력서를 총 5~10 가지 형태로 나눠서 준비했습니다.

 SI / SM / 모바일 / 네트워크 / 솔류션 이렇게 각각의 이력서를 준비하였고.. 그외 솔루션쪽에 개인적으로 3~5장 더 적었네요.( 입사포부나.. 지원동기만 약간 수정하시면 될듯 합니다. )

 이력서 지원분야랑 희망연봉 은 꼭 기재했습니다.

 제 개인적인 생각으론.. 회사내규 또는 얼마에서 얼마 이렇게 적는거보다 딱 뿌려지게.. XXXX 만원 퇴직금 법정 이런식으로 명확히 적는게 좋을듯 합니다.. 회사마다 다르겠지만 거의 1800 만원으로 시작하는게 보통이구요... 만약 다른분보다 스펙은 떨어질꺼 같고 근데.. 자신이 정말 가고 싶은 회사일경우 그냥.. 연봉 -100 -200 더 깍아서 입사률을 높이는 것도 좋은 방법인듯 합니다.. 그렬경우 면접률도 올라갑니다..

 실제로 제가 면접 본곳중 면접관이 이려셨습니다.. 남들은 거의 1800 인데 왜 연봉을 1600 적었느냐? 고 묻길래..

 이 회사에 꼭 들어가서 이런이런 기술적인 부분을 꼭 배우고 싶은데.. 요즘 워낙취업이 어렵고 저 보다 좋은분들이 많아..

이정도의 금액을 받고서라도 정말 열심히 하겟다.. 대충 이런식으로 둘러 되시면.. 좀더 합격률이 올라갈꺼라 봅니다.

 Ps : 2000 에서 1800 으로 깍아서 적는건 효율이 없을듯 합니다.. ㅡㅡ;;;

 같은선상의 스펙 이력서라면.. 왠만한 회사측에선 좋아라 할듯 합니다..  물론 연봉이야 깍이게 겠지만..

자신이 정말 할 자신이 있다 라는분은 추천.. ( 솔루션 업체 추천 / SI 비추 )

 Ps : 자신의 스펙을 아시는게 좋을듯 합니다.

 제 나름대로의 기준을 잡아보자면..

 2200 이상 : 4대졸전공자 / 학원수료자 / 포트폴리오 / 토익or일어 / 기사자격증 / SCJP 일 경우 << 업체가 탄탄할 경우

2000 : 4대졸전공자/ 토익or일어 / 기사자격증orSCJP / 또는.. 초대졸전공자 / 학원수료자 / 포트폴리오 / 산업기사or SCJP

1800 : 4대졸/초대졸전공자 /  기사(산업기사)자격증 혹은.. 고졸 포트폴리오 빵빵한자..

 Ps : 초대졸은 2000 넘기기 힘들다는게 제 생각입니다. ( 태클금지!! )

Ps : 보통 회사측에선.. 4대졸도1800 ~ 2000 생각하는게 보통이더군요..

 이력서는 제가 위에 찐하게 글 적은듯이.. 포인트 줄 경우 저런식 어필하는게 좋을듯 합니다.

 왼쪽 상단에.. '사진' / 오른쪽 상단에 '희망연봉' / 그리고 학원수료 - 학교수료 - 자격증 - 2외국어및 연수 - 타회사경력 이런식으로... 가장 비중있게 될 부분을 젤 위에서 적어나갔구요..

 Ps : 타회사 업무시 전 그냥 안적엇습니다. 공장쪽에 일한 경험이 안좋게 보이더군요.

 포트폴리오 한장이상 기술시.. 확실히.. 면접보시게 될 확률 팍팍 올라갑니다.. 그담에 자소서 적었구요.. 자소서의 경우.. 다른건 동일하게 적었는데.. 회사마다 지원동기를 다르게 보냈습니다. ( SI 솔루션 네트워크 이런식으로.. )

 자소서의 경우 대기업 지원할때처럼.. 한줄 명언 적고.. 그 밑에 추상적인 글을 안적는게 좋을듯 했습니다.

정말 사실적이게 적되.. 최대한 IT 랑 연관지어서 많이 적었습니다.

 제 같은 경우...성장배경은..  무슨계기로 IT 를 하고 싶다는 생각을 했고..그걸 위해 학교에서 뭘 배웠다 이런식으로..  적었구..

성격 장단점은 최대한 끈기 열정 이런거 대표적인 글 보다.. 자신만의 어필(?) 로 하는게 좋을듯 합니다.. 적을꺼 없으면..

그냥 끈기 열정 적구요 ㅡㅡ;; 입사포부 이런건.. 알아서 적으심 되구요.. 끝맺음에 좀 찐하게 남는(?) 그런걸로 어필 하는게 좋을듯 했습니다.. 제 같은 경우는.. 마지막에.. 회사에 이익을 가져다 주는 존재가 되겠습니다!! 라고 어필을 ㅡㅡ;;

 포트폴리오 기술을 어떻게 할지 몰라 고민 많이 했는데요..

 거의 한장썻구요.. URL 까지 기재해서 올렷습니다.. ( 근데 확인은 안하더군요 ㅡㅡ;; )

뭘 구현했고 이런내용보다는.. 포트폴리오 하면서 느낀점을 최대한 많이 적었구요.. 실제적으로 기술적인 부분은 실무면접관이 글을 읽었을때 동감되는 부분이 되게 적는게 좋을듯 합니다.. 포트폴리오 초보자 많이 하는 실수 같은거요.. 예를 들면..

저 같은 경우 java jsp 였는데.. 코딩 하다가 나서.. 오타나서 찾기 힘들엇다 이런것도 적은거 같습니다..

 그리고.. 제 생각엔.. 가장중요한게 문제해결 능력인데요.. 어느부분을 몰라서.. google 검색하고 책 게시판등 다 활용해서..

문제점을 해결했다 이게 직방인거 같네요..

( 여담으로 면접볼때 검색엔진 뭐 쓰냐는 질문에.. 네이버 했다가 떨어졌다는 애기도 들어서 ㅡㅡ;;; )

 만약 포트폴리오 없어서.. 만드시고 싶은신 경우..

 책보시면.. 프로젝트 만드는 책 같은거 있던데.. 한권 사셔서 그거CD 에 보면 소스랑 다 첨부되어 있을겁니다..

완전 초보자가 아니고 좀 공부했다 싶으시면 대충 경로랑.. 이런거 수정 하시고.. 완성해서 첨부하시면 될듯(?) ㅡㅡ;;

 Ps : 의외로 많이 어렵습니다 ㅡㅡ;; 근데 공부도 확실히 됩니다..

 위의 방법처럼 커트라인 스펙 이력서와.. 사실적인 자소서를 적는게 중요한듯 싶습니다..

 요약하자면.. 대학 전공자 or 학원 수료자 / 포트폴리오 3가지면.. 면접까지는 가리라 봅니다. 나머지 부족한 부분은..

포트폴리오로 채우는게 직빵이긴 한데.. 흠흠..

 

2. 면접..

 어떻게든 면접을 보시게 되면.. 가장 많이 들었던 면접내용을 애기해 드릴께요..

 
1. 프로젝트 역활은?? 설명해 보시오.

 대부분 묻더군요.. 면접자들 모두 쇼핑몰 해밨다고.. 회원가입 방명록 답변형 계시판 해밨고.. 하니깐..

제 차례때 애기할꺼 없더라구요.. 그래서 저도 하긴 했는데.. 다른면접자랑 같아지는 분위기고.. 그러니 면접관분들도.. 그냥 그려러니 하던거 같은데.. 만약 저렇게 나올 경우..

 한부분을 애기하더라도.. 정말 세세히 어떻게 구현했는지를 애기 하는게 좋은거 같습니다..  어설프게 설명하다간 바로 거짓 들통나구요.. 최대한 연습해 가시는게 좋을듯 합니다.

 

2. 개발자가 될려고 하는 이유는??

 한 8 군데에서 들었던 질문입니다.. 요즘 학원수료하면 개발자 된다(?) 이런인식 때문에 나온 질문인거 같습니다.

 
3. 혼자서 개발할수 있겠냐?? 어떻게 할꺼냐??

아무래도 개발 투입시 일어날수 있는(?) 문제점을 애기 하는거 같더군요.. 가장 좋은 답변은..

모르면 google 찾아보고.. 게시판 카페 뒤져보고.. 책 찾아보고.. 그담에도 모르면 사수에게 물어보겠다가 답인듯 싶더군요 ;;

기술면접은 보통 이런것들 주로 물어밨구요.. 간혹 필기테스트 2번 밨는데요..

 

필기면접은 JAVA JSP 일 경우..

이 코드가 뭐하는 기능인지 서술하는거랑.. 오버로딩 오버라이딩 차이점?? SQL 문 빈칸 작성 이런것들이랑 디자인패턴 아는거에 대해 설명하시오.. 그외에.. 다른것들 지금 기억나는게 없네요..

그외 면접내용을 보면..

 

4. 만약 야근이나 주말근무 할 수도 있는가??

5. 성격 장단점??

6. 희망연봉은??

 

가장 대답하기 곤란한 질문이었네요.. 이것때문에 떨어진 회사도 잇습니다 ㅠㅠ;;

회사내규에 따르겠습니다 했다가.. 정말로 따르겠냐?? 이러길래 당황했던 기억이.. ㅡㅡ;;

기술적인 면접을 잘밨다 싶으시면 2000 부르고 아니면 1800 부르는게 좋을듯 하네요.. 적정금액 바로 애기 하시는게..

취업을 확실히 하고 싶다 이러시면 걍 1600 부르는것도 ㅡㅡ;;

 

7. 우리회사에 지원한 이유는??

그냥 IT 가 좋아서.. 이 계통으로 일해보고 싶어서 << 비추

최대한 회사에 대한 정보 알아보고 가심이..

 

8. 궁금한 점은??

연봉애기.. 복리후생 돈적인거 빼고 회사의 개발환경이라던지 사수 인원 이런거 물어보면 좋을듯요.

그리고 신입으로 들어갈 경우 맡게될 업무 내용이런거 자세히... << 의외로 중요합니다..

 

9. 공백기간은 경우 무엇을 했는지? 또는 이전회사에서 무엇을 했는지??

공백기간은 정말 면접볼때 최대단점으로 작용했구요.. 다른일 했다 이런거보다 다른일 하면서도 iT 공부했다던가..

iT 연줄을 안놓았다는걸 어필하는게 좋을듯 했습니다.. 이것때문에 떨어진 회사도 있음 ㅡㅡ;;

 

10. 지방에 사시는분의 경우 서울로 올라올 경우.. 연고지는 있냐?? 생활은 어떻게 할꺼냐??

대충 요약하면 이정도구요.. 그외에도 이력서 보면서 하나하나 질문하는 경우도 많았습니다..

주량은?? 술 담배는?? 여자친구는?? 아는 프로그래머가 있냐?? 다룰수 있는 스킬은?? 업무내용이랑 다르면 어떻게 할래??

군대는?? 이직 할꺼냐?? 최근에 읽은 책은?? 3 5 10 년후 자신의 모습은?? 기타등등 많네요..

 그리고 간혹 워크넷 고용촉진비(?) 받을수 있는지 물어보는 회사도 있었습니다.. ㅡㅡ;;

 대충 이렇구요.. 너무 제 애기만 쓴게 아닌지 모르겠네요..

 

일단 인터넷창 띄우시면 무조건 자주가시는 사이트 따로 빼놓구요.. 채용사이트만 딱 보이게 했습니다.

구직사이트는.. 잡코리아 / 데브잡 / 사람인 / 인크루트 / 워크넷 을 주로사용했구요..

채용사이트는 항상 아침 9시쯤 되면 그날 업데이트가 되거든요.. 그래서 보통 12시쯤에 지원하구.. 저녁 9시쯤 지원하구..

이런식으로 2~3번에 걸쳐서 지원하심 될듯하네요..

 

보통 인사당담자들은 출근 하고 1시간뒤 메일 확인하거나.. 아님 퇴근전쯤에 확인을 많이하더라구요..

 

그리고 보시면 아시겠지만 인력파견업체들은 매번 [new] xxxxx 이런식으로 올라오는데..

그런곳은 지원해두 연락이 잘 안오더군요.. 경기가 어려우니 프로젝트 경력자 뽑는거 같더군요..

 

서울에 취업하실분들은 주로.. 구로구.. 강남부근에 업체들이 많이 있구요.. 그외에 마포구.. 영등포구.. 연세대쪽 간간히 있었던거 같네요.

 음 그리고.. 제가 드릴수 있는 정보가 또.. 뭐가 이쓸련지 모르겠네요 ^^;;

 회사측에서 원하는 서류전형 합격선 기준은 대충.. 대졸전공자/학원수료자/포트폴리오 인거 같구요.

 서류전형 합격해두 대부분 동일선상 스펙이기 때문에.. 냉정하게 애기해서.. 연봉을 낮추는 방법이 뽑히는 방법이 지름길이라 생각 되네요 ㅡㅡ;; 아니면.. 면접을 크게 어필하던지.. 또 아니면 1년미만의 신입경력을 갖췃던지요..

 Ps : 저 같은경우는 연봉을 낮춰서 1군데 합격이랑.. 2군데는 면접을 크게 어필해서 합격했습니다. 근데 막상 합격하고 나니.. 연봉적인 부분을 무시못해서.. 괜찮은 조건으로 ^^; 잘갔다고 생각되네요 ㅡㅡ;;

 저 같은 경우는.. 공고생 졸업이라 iT 쪽 계통사람들이 거의 없었거든요..

 친구들도 대부분 조선소나 두산 한진 이런데 들어가서 쇠깍고 있는데 연봉이 3300 정도 되는데.. 난 뭐하고 있나 이런 생각도 막들고.. 그래서.. 공장쪽으로도 막 알아볼까 했었는데.. 전에두 글도 적었지만.. 얼마전 정말 iT 랑 영영 byebye 될뻔 한적도 있었구요.. ;;

 근데 가장 중요한게 끝까지 포기하지 않고 공부하면서 계속 업체 다방면으로 알아 보는게 좋을거 같습니다.

 전 정보 같은거두 잘 없구.. 그냥 이력서 작성하고 지원한는거 말고 답이 없었거든요..

그렇게 한 3개월 가량~ 조마조마 하고 살았는데~ 이런식으로 글 작성하다 보니.. 커뮤니티(?) 사이트 이런곳에서..

 응원해주는분들이 있었기에.. 그 분들과 애기도 하면서 많은 힘이 되었고.. 서서히 인맥을 키워 나갈려고 합니다..

 최대한 커뮤니티 사이트를 이용해서.. 실무자와 애기 나눠보시고.. 방향을 제시 받으시길 바랍니다..

듣을껀 듣고 거를껀 거르고.. 아무튼.. 제가 느낀점은 어느정도 적은거 같네요..

출처 : 데브피아


/**
 * Oracle10g 부터는  CLOB 데이터 타입을 처리하는 방법이 간단해 졌습니다.
 *
 *   -- scott/tiger에 테스트 테이블 생성
 *   create table clob_test (contents clob);    
 *
 * - 첫 번째 방법 SetBigStringTryClob을 true 로 설정한 후 처리 하는 방법 입니다.
 * - 두 번째 방법 OraclePreparedStatement의 setStringForClob 메소드를 이용하는 방법 입니다.
 * - 자세한 내용은 아래 링크를 참고해 주세요.
 *  참고링크
 *
 */   
 
 
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
 
public class CLOBTypeTest {
 
        
    public static void main(String[] args){
        
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rset = null;
        String user     = "scott";
        String password = "tiger";
        String url      = "jdbc:oracle:thin:@localhost:1521:ora10g";
        
        try{
            
            StringBuffer str = new StringBuffer();

            for(int i=0 ; i<10000; i++){
                str.append(" CLOB Test Data ");
            }
            
            System.out.println(" INSERT CLOB length:  "+str.length());
            
            Properties props = new Properties();
            props.put("user", user );
            props.put("password", password);
            props.put("SetBigStringTryClob", "true");
            
            DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver());            
            conn = DriverManager.getConnection (url, props);
            
            pstmt = (PreparedStatement)conn.prepareStatement(" INSERT INTO clob_test VALUES(?) ");
            
            pstmt.setString(1, str.toString());
            pstmt.executeUpdate();
            
            pstmt.close();
            
            String sqlCall = "SELECT contents FROM clob_test WHERE rownum = 1 ";
            pstmt= conn.prepareStatement(sqlCall);
            
            rset = pstmt.executeQuery();     
            String clobVal = null;       
            
            while (rset.next()) {  
                clobVal = rset.getString(1);  
                System.out.println(" SELECT CLOB length: "+clobVal.length());     
            }
            
        }catch(SQLException sqle){
            sqle.printStackTrace();
        }finally {
            try {
                if (rset != null)
                    rset.close();
                if (pstmt != null)
                    pstmt.close();
                if (conn != null)
                    conn.close();
            } catch (SQLException se) {
            }           
        }  
    }
        
}

출처 : http://www.oracleclub.com/lectureview.action

Java Sound, Audio File Conversion
By Richard G. Baldwin

Java Programming Notes # 2024


Preface

This series of lessons is designed to teach you how to use the Java Sound API.  The first lesson in the series was entitled Java Sound, An Introduction.  The previous lesson was entitled Java Sound, Creating, Playing, and Saving Synthetic Sounds.

Two types of audio data

Two different types of audio data are supported by the Java Sound API:

  • Sampled audio data
  • Musical Instrument Digital Interface (MIDI) data

The two types of audio data are very different.  I am concentrating on sampled audio data at this point in time.  I will defer my discussion of MIDI until later.

Viewing tip

You may find it useful to open another copy of this lesson in a separate browser window.  That will make it easier for you to scroll back and forth among the different listings and figures while you are reading about them.

Supplementary material

I recommend that you also study the other lessons in my extensive collection of online Java tutorials.  You will find those lessons published at Gamelan.com.  However, as of the date of this writing, Gamelan doesn't maintain a consolidated index of my Java tutorial lessons, and sometimes they are difficult to locate there.  You will find a consolidated index at www.DickBaldwin.com.

Material in earlier lessons

Earlier lessons in this series showed you how to:

  • Create, play, and save synthetic sounds, making use of the features of the java.nio package to help with the byte manipulations.
  • Use methods of the AudioSystem class to write more robust audio programs.
  • Play back audio files, including those that you create using a Java program, and those that you acquire from other sources.
  • Capture microphone data into audio files types of your own choosing.
  • Capture microphone data into a ByteArrayOutputStream object.
  • Use the Sound API to play back previously captured audio data.
  • Identify the mixers available on your system.
  • Specify a particular mixer for use in the acquisition of audio data from a microphone.
  • Understand the use of lines and mixers in the Java Sound API.

This lesson will show you how to perform file conversions among different audio file types.

Preview

Audio file type is different from audio encoding

Numerous audio file types have been defined in recent years, including AU files, AIF files, and WAV files.  However, when trying to determine if a particular audio file will be satisfactory for a particular application, simply knowing the file type isn't sufficient.  You must also know how the audio data is encoded within the file.

Stated simply, the file type specification indicates how the bytes are physically arranged within the file.  The encoding specification indicates how the audio information is arranged within the bytes.  Not all file types can accommodate all encodings.  However, many file types can accommodate several different encodings.

As it turns out, file types are the less complex of the two topics.  I will deal with file types in this lesson.  I will begin dealing with encodings in the next lesson.

Information on different file types

Here are descriptions of some of the file types supported by Sun's Java, as found at the High-Tech Dictionary of File Types:

  • AU - A sound file format used on Sun Microsystems or other UNIX computers.
  • AIF - Audio Interchange File Format or AIFF (filename extension). A format developed by Apple Computer for storing high-quality sampled audio and musical instrument information. It can be played on PC and Mac.  (Note that the Sun Java API treats the common filename extension for this type as AIF.)
  • WAV - Sound file.  (As you can see, the HighTech Dictionary doesn't have much to say about this file type.  I will add that most of the sound files that are provided by Microsoft in a typical Windows installation are WAV files.)

Format descriptions

You can view a technical description of the format of an AU file, including information about how the bytes are arranged in the file, at Header file for Audio, .au.

You can view a similar technical description for an AIFF file format here.  Finally, you can view a technical description of the format of a WAV file at The Canonical WAVE File Format.

Of course, if you fire up your Google search engine, you can find many other descriptions of these and other file formats as well.

General information about sampled sound

You will find some very interesting information about sampled sound published by Marc Boots-Ebenfield at Sound Formats. Included on the web site is the following factoid regarding CD quality music.

"On a Music CD the music is sampled at 44.1 KHz using 16 bit words or 705,600 bits for each second of sound. At 8 bits to the byte that would mean that 1 second of CD quality music would occupy 88,200 bytes or 88 Kb of your floppy disc which holds 1.2 Mb of data. That means that you could hold 13 seconds of CD quality music on a floppy- (uncompressed)!"

If the above estimate is correct, then about fifteen floppy disks would be required to contain a typical three-minute song in uncompressed CD quality format.  (That fact will be more important in the future lessons on encoding than in this lesson.)

A non-technical aside

As another interesting factoid, The American Heritage® Book of English Usage is not very fond of this usage of the word factoid.

Discussion and Sample Code

The user interface

The user interface for this program is very simple.  This program is designed to be executed from the command line as follows:

Usage: java AudioFileConvert01 inputFile outputFile

The program named AudioFileConvert01

Before getting into the details of the program code, I will describe the program and show you some examples produced by running the program.

This program demonstrates the ability to write a Java program to convert one audio file type to a different audio file type.  Run the program by entering the following at the command line:

java AudioFileConvert01 inputFile outputFile

Input and output file types

The type of output file that is created depends on the output file name extension, such as au, wav, or aif.

On the other hand, the type of the input file does not depend on the input file name or extension.  The actual type of the input file is determined by the program irrespective of the name of the file or the extension given to that file.

Playback of the output file

You should be able to play the output file with any standard media player that can handle the file type, or with a program written in Java, such as the program named AudioPlayer02 that was developed in an earlier lesson.

Operational examples

The following paragraphs show sample screen outputs for different input and output file types.  Note that line breaks were manually inserted to force the material to fit in this narrow publication format.

Valid input file with invalid file extension

In the first example, shown in Figure 1, a valid input wav file named ringout was forced to have the invalid extension .txt.  However, the program successfully determined the type of the wav file on the fly, and the wav file was successfully converted to an au file.

(You may recognize the primary name of this file as being one of the sound files commonly included in a standard Windows installation.  I simply made a copy of the file named ringout.wav and changed the extension before running this experiment.)

java AudioFileConvert01 ringout.txt junk.au
 Input file: ringout.txt
 Output file: junk.au
 Output type: au
 Output type is supported
 Input file format:
 WAVE (.wav) file, byte length: 5212,
 data format: PCM_UNSIGNED, 11025.0 Hz,
 8 bit, mono, audio data
 Bytes written: 5191
 Output file format:
 AU (.au) file, byte length: 5191,
 data format: PCM_SIGNED, 11025.0 Hz,
 8 bit, mono, audio data, frame length: 5167
Figure 1

Encoding information is displayed

You will see the code that produced the output in Figure 1 later when I discuss the program.  As you can see from the output, the code in this program gets and displays encoding information (PCM_UNSIGNED, 8 bit, mono, etc.) on both the input file and the output file in addition to the file type.  However, this program makes no attempt to purposely change the encoding.   (As I mentioned earlier, I will begin dealing with encoding in the next lesson.)

Conversion of an AU file to a WAV file

In the example shown in Figure 2, the input file was a stereo au file produced by a sample program from an earlier lesson.  The au file was successfully converted to a wav file.
 

java AudioFileConvert01 junk3.au junk.wav
 Input file: junk3.au
 Output file: junk.wav
 Output type: wav
 Output type is supported
 Input file format:
 AU (.au) file, byte length: 64024,
 data format: PCM_SIGNED, 16000.0 Hz, 16 bit,
 stereo, big-endian, audio data,
 frame length: 16000
 Bytes written: 64044
 Output file format:
 WAVE (.wav) file, byte length: 64044,
 data format: PCM_SIGNED, 16000.0 Hz, 16 bit,
 stereo, little-endian, audio data
Figure 2

The fact that these files are stereo (two-channel) files is indicated by the encoding information that is displayed in Figure 2.

Conversion of a WAV file to an AIF file

A standard Windows monaural wav file was successfully converted to an aif file, as shown in Figure 3
 

java AudioFileConvert01 ringout.wav junk.aif
 Input file: ringout.wav
 Output file: junk.aif
 Output type: aif
 Output type is supported
 Input file format:
 WAVE (.wav) file, byte length: 5212,
 data format: PCM_UNSIGNED, 11025.0 Hz, 8 bit,
 mono, audio data
 Bytes written: 5221
 Output file format:
 AIFF (.aif) file, byte length: 5221,
 data format: PCM_SIGNED, 11025.0 Hz, 8 bit,
 mono, audio data, frame length: 5167
Figure 3

An unsupported output file type

In the example shown in Figure 4, the specified output file type, xyz, is not supported by the Java Sound API (nor by any other system that I am aware of).  Therefore, the program aborted, providing a list of the output file types that are supported for writing by the system.
 

java AudioFileConvert01 junk3.au junk.xyz
 Input file: junk3.au
 Output file: junk.xyz
 Output type: xyz
 Output type not supported.
 Supported audio file types: au aif wav
Figure 4

Note that the Java implementation on my system at the time of this writing only supports file types au, aif, and wav.

An unsupported input file type

In the example shown in Figure 5, the input file claimed by virtue of its name and extension to be a wav file.  However, it was not a valid audio file.  Rather, it was simply a text file that I renamed to cause it to impersonate a wav file.  This caused the program to throw an UnsupportedAudioFileException and abort.

Once again, the program determined the type of the input file by examining the contents of the file, and not by examining the file's name or extension.
 

java AudioFileConvert01 invalidFile.wav junk.au
 Input file: invalidFile.wav
 Output file: junk.au
 Output type: au
 Output type is supported
 javax.sound.sampled.
 UnsupportedAudioFileException: could not get
 audio input stream from input stream
 at javax.sound.sampled.AudioSystem.
 getAudioInputStream(AudioSystem.java:756)
 at AudioFileConvert01.
 main(AudioFileConvert01.java:84)
Figure 5

Getting usage information

In Figure 6, the program was run with no command-line arguments, causing the program to provide usage information and abort.
 

java AudioFileConvert01
Usage: java AudioFileConvert01
                            inputFile outputFile
Figure 6

This program was tested using SDK 1.4.1 under WinXP

The class named AudioFileConvert01

The controlling class for the program begins in Listing 1.  As usual, I will discuss the program in fragments.  You can view a listing of the entire program in Listing 11 near the end of the lesson.

The program is relatively straightforward consisting of the main method and the following static methods (these methods were declared static so that they can be invoked from inside the main method):

  • getTargetTypesSupported - returns a list of the audio file types that can be written by the system.
  • getTargetType - returns the type of a specified output file based on the filename extension.
  • showFileType - Examines a File object representing a physical audio file and displays information about the file.

The main method

Listing 1 contains the beginning of the main method.  The code in Listing 1 examines the number of command-line arguments entered by the user, and displays usage information if the user didn't enter any arguments.
 

public class AudioFileConvert01{

public static void main(String[] args){
if(args.length != 2){
System.out.println(
"Usage: java AudioFileConvert01 "
+ "inputFile outputFile");
System.exit(0);
}//end if

System.out.println("Input file: " + args[0]);
System.out.println("Output file: "+ args[1]);

Listing 1

In addition, the code in Listing 1 displays the input and output file names provided by the user when those file names are entered as command-line arguments.

Get and test output file type

The output file type is determined by the filename extension provided by the user.  The code in Listing 2 isolates the filename extension as type String and displays the extension on the screen.

    String outputTypeStr =
args[1].substring(args[1].
lastIndexOf(".") + 1);
System.out.println("Output type: "
+ outputTypeStr);

AudioFileFormat.Type outputType =
getTargetType(outputTypeStr);

Listing 2

More importantly, the code in Listing 2 invokes the getTargetType method, passing the filename extension as a String parameter to that method.

The getTargetType method

The getTargetType method checks to see if the system is capable of writing the file type indicated by the extension.  If so, it returns an AudioFileFormat.Type object matching that extension.  If not, it returns null.

At this point, I am going to put the main method on hold and discuss the method named getTargetType.

The AudioFileFormat.Type class

Listing 3 contains the entire method named getTargetType.

  private static AudioFileFormat.Type
getTargetType(String extension){
AudioFileFormat.Type[] typesSupported =
AudioSystem.getAudioFileTypes();
//System.out.println("length: " +
typesSupported.length);
for(int i = 0; i < typesSupported.length;
i++){
if(typesSupported[i].getExtension().
equals(extension)){
return typesSupported[i];
}//end if
}//end for loop
return null;//no match
}//end getTargetType

Listing 3

The first thing to note about the code in Listing 3 is that the getTargetType method returns a reference to an object of type AudioFileFormat.Type.

(In case you are unfamiliar with the notation where there is a period in a class name, this indicates that the Type class is an inner class of the class named AudioFileFormat.  If you are unfamiliar with inner classes, see the tutorial lessons on that topic on my web site.)

What does Sun have to say?

Here is what Sun has to say about this class:

"An instance of the Type class represents one of the standard types of audio files. Static instances are provided for the common types."

Static instances are provided for the following types:

  • AIFC
  • AIFF
  • AU
  • SND
  • WAVE

It is interesting to note that even though five different audio file types are identified as the common types in this class, only three of those types are currently supported for writing on my machine running SDK 1.4.1 under WinXP.

An array of AudioFileFormat.Type object references

The code in Listing 3 invokes the method named getAudioFileTypes, which is a static method of the AudioSystem class.  This method returns a list containing "the file types for which file writing support is provided by the system."  This list is stored in an array of type AudioFileFormat.Type.

(Listing 3 contains a statement with a call to the println method that has been commented out.  When this statement is enabled on my system, it reports that the length of the array is three, indicating that only three file types are currently supported for writing on my System.  You will see the names of those three types later.)

The getExtension method

The AudioFileFormat.Type class provides a method named getExtension, which returns "the common file name extension" for an object of the type.  The code in Listing 3 uses a for loop to search the array of AudioFileFormat.Type objects looking for a match to the file name extension received as an incoming parameter by the getTargetType method.

If a match is found, the AudioFileFormat.Type object corresponding to that match is returned by the getTargetType method.  Otherwise, null is returned by the method.

Testing the return value

Returning our attention to the code in the main method, the code in Listing 4 tests to determine if a null value was returned by the getTargetType method.  If not, the program displays the message:

Output type is supported
 

//Continue with main method
if(outputType != null){
System.out.println(
"Output type is supported");
}else{
System.out.println(
"Output type not supported.");
getTargetTypesSupported();
System.exit(0);
}//end else

Listing 4

If a null value was returned by the getTargetType method, the program displays the following message and then invokes the method named getTargetTypesSupported to display a list of the file types that are supported for writing by the system.

Output type not supported.

The getTargetTypesSupported method

The purpose of the method named getTargetTypesSupported is to get and display a list of the file types supported for writing by the system.

Once again, I'm going to put the main method on hold while I discuss the method named getTargetTypesSupported, shown in Listing 5.
 

  private static void getTargetTypesSupported(){
AudioFileFormat.Type[] typesSupported =
AudioSystem.getAudioFileTypes();
System.out.print(
"Supported audio file types:");
for(int i = 0; i < typesSupported.length;
i++){
System.out.print(" " +
typesSupported[i].getExtension());
}//end for loop
System.out.println();
}//end getTargetTypesSupported

Listing 5

Get and display common filename extensions

The code in Listing 5 shouldn't require much in the way of an explanation.  This code is very similar to the code in Listing 3.  In Listing 5, however, after getting an array of AudioFileFormat.Type objects representing the file types supported for writing by the system, the code simply gets and displays the common filename extension for each of those types.

For the example discussed previously (see Figure 4) where I purposely told the program to write an unsupported output file type (xyz), the code in Listings 4 and 5 produced the output shown in Figure 7.
 

 Output type not supported.
 Supported audio file types: au aif wav
Figure 7

(Note that the list of supported file types in Figure 7 includes only three of the five types identified by static instances of the AudioFileFormat.type class.)

The input file type

Returning once again to the main method, the code in Listing 6 begins dealing with the input file.

(Note that the determination of the input file type does not depend on the file name or extension.  Rather, the program determines the type of the input file by extracting information about the file from the information contained in the file itself.)

Get an AudioInputStream object

The code in Listing 6 begins by getting a File object that represents the input file.

//Continue with main method
File inputFileObj = new File(args[0]);
AudioInputStream audioInputStream = null;
try{
audioInputStream = AudioSystem.
getAudioInputStream(inputFileObj);
}catch (Exception e){
e.printStackTrace();
System.exit(0);
}//end catch

Listing 6

Then the code in Listing 6 uses that File object to get an AudioInputStream object that can be used to read the audio data in the input file.

I have discussed code involving AudioInputStream objects in several previous lessons.  Therefore, I won't bore you by discussing it again here.

Display file type information

The code in Listing 7 invokes the showFileType method for the purpose of displaying information about the input file type.
 

    System.out.println("Input file format:");
showFileType(inputFileObj);

Listing 7

The showFileType method

Once again, I'm going to put the main method on hold while I discuss the method named showFileType, shown in Listing 8.
 

  private static void showFileType(File file){
try{
System.out.println(AudioSystem.
getAudioFileFormat(file));
}catch(Exception e){
e.printStackTrace();
System.exit(0);
}//end catch
}//end showFileFormat

Listing 8

There isn't much to the showFileType method.  It simply invokes the method named getAudioFileFormat, which is a static method of the AudioSystem class, passing the File object that represents the input file as a parameter to the method.

The getAudioFileFormat method

Here is what Sun has to say about the getAudioFileFormat method.

"Obtains the audio file format of the specified File. The File must point to valid audio file data."

This method returns an object of type AudioFileFormat, whose reference is passed to the println method for display.

The AudioFileFormat class

Here is what Sun has to say about an object of this class:

"An instance of the AudioFileFormat class describes an audio file, including the file type, the file's length in bytes, the length in sample frames of the audio data contained in the file, and the format of the audio data."

As is frequently the case, this class has an overridden toString method, which facilitates displaying information about the contents of the object.

The screen output for a supported input file type

Figure 8 shows the screen output produced by Listings 7 and 8 for a supported audio input file of type WAV:
 

 Input file format:
 WAVE (.wav) file, byte length: 5212,
 data format: PCM_UNSIGNED, 11025.0 Hz, 8 bit,
 mono, audio data
Figure 8

Note that this output contains the number of channels and the sampling frequency, which is not mentioned in the quotation from sun in the previous section.

The screen output for an unsupported input file type

Figure 9 shows the screen output produced by Listing 6 when an attempt was made to get an AudioInputStream object on a file that was not a valid audio file.  (It was a text file of the type produced by the Windows NotePad program.)
 

 javax.sound.sampled.
 UnsupportedAudioFileException: could not get
 audio input stream from input stream
 at javax.sound.sampled.AudioSystem.
 getAudioInputStream(AudioSystem.java:756)
 at AudioFileConvert01.
 main(AudioFileConvert01.java:84)
Figure 9

In this case, the program didn't even make it far enough to invoke the showFileType method for the purpose of displaying information about the file.  Rather, it threw an UnsupportedAudioFileException when the attempt was made to get an AudioInputStream object on the input file.

The bottom line on file conversion

Returning once more to the main method, the code in Listing 9 illustrates the bottom line on audio file conversion in Java.

(Note that I deleted the try and catch from Listing 9 in order to simplify the presentation.  You can view that code in Listing 11 near the end of the lesson.)

//Continue with main method
int bytesWritten = 0;
//delete try
bytesWritten = AudioSystem.
write(audioInputStream,
outputType,
new File(args[1]));
//delete catch
System.out.println("Bytes written: "
+ bytesWritten);
Listing 9

The write method of the AudioSystem class

As it turns out, doing audio file conversion using the Java Sound API is relatively simple, as long as you aren't trying to change encodings in the process.  (As mentioned earlier, I will begin discussing encodings in the next lesson.)

(Much of the code in this program was provided to help you to understand what is going on.  A version of the program named AudioFileConvert02, with most of the unnecessary code deleted, is shown in Listing 12 near the end of the lesson.)

The basics of file conversion

All that is really necessary to do a file conversion using the Java Sound API is:

  • Get the names of the input and output files.
  • Get an object of the class AudioFileFormat.Type, which defines the type of the output file.
  • Get an AudioInputStream object on the input file.
  • Invoke the method named write shown in Listing 9 passing the above information as parameters to the write method.

This will cause the input file to be read, and will cause the data from the input file to be written into the output file in the specified format.

The write method

Here is what Sun has to say about the write method used in Listing 9, which is a static method of the AudioSystem class:

"Writes a stream of bytes representing an audio file of the specified file type to the external file provided"

Can be more general

In reality, this code could be made much more general than it is in this program.  For example, the AudioInputStream object doesn't have to be based on a file.  The AudioInputStream object could be based on a TargetDataLine object, or on any InputStream object capable of supplying audio data according to a known AudioFormat.

Similarly, another overloaded version of the write method allows you to replace the File object in the third parameter with any OutputStream object capable of accepting a stream of audio data in a specified format.

The number of bytes written into the output file

The write method returns the number of bytes actually written.  This value is displayed on the screen by the last statement in Listing 9.

Information about the output file format

The code in Listing 10 displays information about the output file format.
 

    System.out.println("Output file format:");
showFileType(new File(args[1]));

}//end main

Listing 10

Figure 10 shows a sample of the output produced by Listing 10 for one of the example cases discussed earlier in this lesson:
 

 Output file format:
 WAVE (.wav) file, byte length: 64044,
 data format: PCM_SIGNED, 16000.0 Hz, 16 bit,
 stereo, little-endian, audio data
Figure 10

Run the Program

At this point, you may find it useful to compile and run the programs shown in Listings 11 and 12 near the end of the lesson.  Operating instructions were provided earlier in the section entitled The user interface.

If you use a media player, such as the Windows Media Player, to play back your file, be sure to release the old file from the media player before attempting to create a new file with the same name and extension.  Otherwise, the program will not be able to create the new file, and a runtime error will occur.

Also be aware that these programs were tested using SDK version 1.4.1.  Therefore, I can't be certain that they will compile and run correctly with earlier versions of Java.

Summary

In this lesson, I showed you how to convert audio data from one audio file type to another.  The essential steps involved in making such a conversion are:

  • Get the names of the input and output files.
  • Get an object of the class AudioFileFormat.Type, which defines the type of the output file.
  • Get an AudioInputStream object on the input file.
  • Invoke the method named write shown in Listing 9 passing the above information as parameters to the write method.

I also explained that this program could be made much more general either by basing the AudioInputStream object on an InputStream object other than a file, or by causing the output to be an OutputStream other than a file.

You should be able to play the output file produced by this program with any standard media player that can handle the file type, or with a program written in Java, such as the program named AudioPlayer02 that was developed in an earlier lesson.

What's Next?

In the next lesson, I will show you how to use mu-law encoding and decoding to compress and restore 16-bit linear PCM samples.

Complete Program Listing

Complete listings of the two programs discussed in this lesson are shown in Listing 11 and Listing 12.
 
/*File AudioFileConvert01.java
Copyright 2003, R.G.Baldwin

This program demonstrates the ability to write a
Java program to convert one audio file type to a
different audio file type.

Usage: java AudioFileConvert01
inputFile outputFile

Output file type depends on the output file name
extension, such as au, wav, or aif.

Input file type does not depend on input file
name or extension. Actual type of input file is
determined by the program irrespective of name
or extension.

You should be able to play the output file with
any standard media player that can handle the
file type, or with a program written in Java,
such as the program named AudioPlayer02 that was
discussed in an earlier lesson.

The following are sample screen outputs for
different input and output file types. Note that
line breaks were manually inserted to force the
material to fit in this narrow publication
format.

In this example, the valid input wav file was
forced to have an invalid file extension. The
wav file was successfully converted to
an au file.

java AudioFileConvert01 ringout.txt junk.au
Input file: ringout.txt
Output file: junk.au
Output type: au
Output type is supported
Input file format:
WAVE (.wav) file, byte length: 5212,
data format: PCM_UNSIGNED, 11025.0 Hz,
8 bit, mono, audio data
Bytes written: 5191
Output file format:
AU (.au) file, byte length: 5191,
data format: PCM_SIGNED, 11025.0 Hz,
8 bit, mono, audio data, frame length: 5167

In this example, the input file was a stereo au
file produced by a sample program from an earlier
lesson. The au file was successfully converted
to a wav file.

java AudioFileConvert01 junk3.au junk.wav
Input file: junk3.au
Output file: junk.wav
Output type: wav
Output type is supported
Input file format:
AU (.au) file, byte length: 64024,
data format: PCM_SIGNED, 16000.0 Hz, 16 bit,
stereo, big-endian, audio data,
frame length: 16000
Bytes written: 64044
Output file format:
WAVE (.wav) file, byte length: 64044,
data format: PCM_SIGNED, 16000.0 Hz, 16 bit,
stereo, little-endian, audio data

In this example, the input file was a standard
Windows wav file, which was successfully
converted to an aif file.

java AudioFileConvert01 ringout.wav junk.aif
Input file: ringout.wav
Output file: junk.aif
Output type: aif
Output type is supported
Input file format:
WAVE (.wav) file, byte length: 5212,
data format: PCM_UNSIGNED, 11025.0 Hz, 8 bit,
mono, audio data
Bytes written: 5221
Output file format:
AIFF (.aif) file, byte length: 5221,
data format: PCM_SIGNED, 11025.0 Hz, 8 bit,
mono, audio data, frame length: 5167

In this example, the output file was specified
with an unsupported type. Thus, the program
aborted, providing a list of the output file
types that are supported.

java AudioFileConvert01 junk3.au junk.xyz
Input file: junk3.au
Output file: junk.xyz
Output type: xyz
Output type not supported.
Supported audio file types: au aif wav

In this example, although the input file claimed
to be a wav file, it was not a valid audio file.
Rather, it was a text file that was renamed to
impersonate a wav file. This caused the program
to throw a runtime exception and abort.

java AudioFileConvert01 invalidFile.wav junk.au
Input file: invalidFile.wav
Output file: junk.au
Output type: au
Output type is supported
javax.sound.sampled.
UnsupportedAudioFileException: could not get
audio input stream from input stream
at javax.sound.sampled.AudioSystem.
getAudioInputStream(AudioSystem.java:756)
at AudioFileConvert01.
main(AudioFileConvert01.java:84)

In this example, the program was run with no
command-line parameters, causing the program to
provide usage information and abort.

java AudioFileConvert01
Usage: java AudioFileConvert01
inputFile outputFile


Tested using SDK 1.4.1 under WinXP
************************************************/


import java.io.*;
import javax.sound.sampled.*;

public class AudioFileConvert01{

public static void main(String[] args){
if(args.length != 2){
System.out.println(
"Usage: java AudioFileConvert01 "
+ "inputFile outputFile");
System.exit(0);
}//end if

System.out.println("Input file: " + args[0]);
System.out.println("Output file: "+ args[1]);

//Output file type depends on output file
// name extension.
String outputTypeStr =
args[1].substring(args[1].
lastIndexOf(".") + 1);
System.out.println("Output type: "
+ outputTypeStr);
AudioFileFormat.Type outputType =
getTargetType(outputTypeStr);
if(outputType != null){
System.out.println(
"Output type is supported");
}else{
System.out.println(
"Output type not supported.");
getTargetTypesSupported();
System.exit(0);
}//end else

//Note that input file type does not depend
// on file name or extension.
File inputFileObj = new File(args[0]);
AudioInputStream audioInputStream = null;
try{
audioInputStream = AudioSystem.
getAudioInputStream(inputFileObj);
}catch (Exception e){
e.printStackTrace();
System.exit(0);
}//end catch

System.out.println("Input file format:");
showFileType(inputFileObj);

int bytesWritten = 0;
try{
bytesWritten = AudioSystem.
write(audioInputStream,
outputType,
new File(args[1]));
}catch (Exception e){
e.printStackTrace();
System.exit(0);
}//end catch
System.out.println("Bytes written: "
+ bytesWritten);
System.out.println("Output file format:");
showFileType(new File(args[1]));

}//end main

private static void getTargetTypesSupported(){
AudioFileFormat.Type[] typesSupported =
AudioSystem.getAudioFileTypes();
System.out.print(
"Supported audio file types:");
for(int i = 0; i < typesSupported.length;
i++){
System.out.print(" " +
typesSupported[i].getExtension());
}//end for loop
System.out.println();
}//end getTargetTypesSupported

private static AudioFileFormat.Type
getTargetType(String extension){
AudioFileFormat.Type[] typesSupported =
AudioSystem.getAudioFileTypes();
for(int i = 0; i < typesSupported.length;
i++){
if(typesSupported[i].getExtension().
equals(extension)){
return typesSupported[i];
}//end if
}//end for loop
return null;//no match
}//end getTargetType

private static void showFileType(File file){
try{
System.out.println(AudioSystem.
getAudioFileFormat(file));
}catch(Exception e){
e.printStackTrace();
System.exit(0);
}//end catch
}//end showFileFormat
}//end class

Listing 11

 

/*File AudioFileConvert02.java
Copyright 2003, R.G.Baldwin

This program demonstrates the ability to write a
Java program to convert one audio file type to a
different audio file type. This is an updated
version of AudioFileConvert01 in which all
unnecessary code has been removed.

Usage: java AudioFileConvert02
inputFile outputFile

Output file type depends on the output file name
extension, such as au, wav, or aif.

Input file type does not depend on input file
name or extension. Actual type of input file is
determined by the program irrespective of name
or extension.

You should be able to play the output file with
any standard media player that can handle the
file type, or with a program written in Java,
such as the program named AudioPlayer02 that was
discussed in an earlier lesson.


Tested using SDK 1.4.1 under WinXP
************************************************/


import java.io.*;
import javax.sound.sampled.*;

public class AudioFileConvert02{

public static void main(String[] args){
if(args.length != 2){
System.out.println(
"Usage: java AudioFileConvert02 "
+ "inputFile outputFile");
System.exit(0);
}//end if

AudioFileFormat.Type outputType =
getTargetType(args[1].substring(args[1].
lastIndexOf(".") + 1));

if(outputType == null){
System.out.println(
"Output type not supported.");
System.exit(0);
}//end else

File inputFileObj = new File(args[0]);
AudioInputStream audioInputStream = null;
try{
audioInputStream = AudioSystem.
getAudioInputStream(inputFileObj);

AudioSystem.write(audioInputStream,
outputType,
new File(args[1]));
}catch (Exception e){
e.printStackTrace();
System.exit(0);
}//end catch

}//end main
//-------------------------------------------//

private static AudioFileFormat.Type
getTargetType(String extension){
AudioFileFormat.Type[] typesSupported =
AudioSystem.getAudioFileTypes();
for(int i = 0; i < typesSupported.length;
i++){
if(typesSupported[i].getExtension().
equals(extension)){
return typesSupported[i];
}//end if
}//end for loop
return null;//no match
}//end getTargetType
//-------------------------------------------//
}//end class

Listing 12

 


Copyright 2003, Richard G. Baldwin.  Reproduction in whole or in part in any form or medium without express written permission from Richard Baldwin is prohibited.

About the author

Richard Baldwin is a college professor (at Austin Community College in Austin, TX) and private consultant whose primary focus is a combination of Java, C#, and XML. In addition to the many platform and/or language independent benefits of Java and C# applications, he believes that a combination of Java, C#, and XML will become the primary driving force in the delivery of structured information on the Web.

Richard has participated in numerous consulting projects and he frequently provides onsite training at the high-tech companies located in and around Austin, Texas.  He is the author of Baldwin's Programming Tutorials, which has gained a worldwide following among experienced and aspiring programmers. He has also published articles in JavaPro magazine.

Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.

Baldwin@DickBaldwin.com

-end-


  1. Wave File 구조
    • 3개의 Chunk로 이루어져 있다.
    • Chunk란 말이 생소하다면 블록이라 생각하시면 이해가 쉬울것이다.
    • 음성이나 여상 파일은 다른 파일에 비해 매우 크다. 이런 이유 때문에여러 개의 블록으로 나누어 저장하는 방식을 취한다.
    • 이러한 방식의 파일을 RIFF(Resoure Interchange File Format)이라 한다.
    • 멀티이디어의 특별한 유형의 파일 포맷이다.
    • 나뉘어 지는 블록이 Chunk인데 보통 세 개의 Chunk로 나뉘어 진다.
  2. 첫 번째 Chunk는 부모 Chunk라 하여 여기에는
    • 자신의 Chunk ID와
    • 파일의 종류를 알려주는 fccType
    • Data Field를 가지고 있다.

    부모 Chunk ckid="RIFF"
    cksize
    fccType="WAVE"

    Data Field

    자식 Chunk

    Format Chunk

    Chunk ID="fmt"
    Chunk Size=16 byte
    Format data

    Data Chunk

    ckid="data"
    cksize
    Data

  3. 부모 Chunk
    • Chunk ID(ckid) => 자신의 Chunk ID
    • fccType = > 파일의 종류를 알려주기 위한 4 개의 문자로 구성되어 있다.
                         Wave파일에는 "WAVE"로 되어 Type를 알려준다.
    • cksize
    • Data Field => 자식Chunk Format Chunk 와 Data chunk로 구성 되어있다.
  4. 자식 Chunk
    • Format Chunk
      • chunk ID(ckid) => "fm t"라는 무자가 들어가 있음.
        * 중요
        chid,fccType는 항상 4개의 문자로 채워져야 합니다.
        따라서 fmt 다음에 공백("fmt ")까지 포함되어 있어야 합니다.
      • cksize => Wave파일에서는 16 byte 크기의 Foramt data를 가지고 있음.
      • Wave Format = >이 정보는 WAVEFORMATEX 구조체가 가지고 있음.
      • WAVEFORAMTEX의 구조

        typedef struct {
            WORD  wFormatTag;
            WORD  nChannels;
            DWORD nSamplesPerSec;
            DWORD nAvgBytesPerSec;
            WORD  nBlockAlign;
            WORD  wBitsPerSample;
            WORD  cbSize;
        } WAVEFORMATEX;

        멤버 변수 설 명
        wFormatTag Wave Format의 형식
        nChannels Wave 파일에서 사용하는 채널 수
        nSamplesPerSec 초당 sample 수
        nAvgBytesPerSec 초당 데이터의 평균 바이트 수
        nBlockAlign 샘플당 바이트수 * 채널 수
        wBitsPerSample 샘플당 bit 수
        cbSize 항상 0
    • Data Chunk(실제적인 파일의 data를 가지고 있음.)<

starup코드는 C소스상에서 액세스 하기 힘든 초기화 과정을 C코드의 main함수가 실행되기 이전에 실행되는

ASM코드 입니다. 따라서 주된 내용은 스택의설정, 각 메모리컨트롤러 설정, 익셉션처리 설정, 인터럽트 벡터테이블

설정등입니다. 따라서 startup코드는 프로그램을 작성할 때 항상 따라온다고 보시면됩니다. startup 코드 실행이

끝나면 C소스코드의 main함수가 실행되도록 하는 jump루틴이 들어가 있습니다. 다만 ASM코드만 즉 startup코드만

가지고 간단한 프로그램을 작성하기도 합니다.

 

  Boot코드는 부트과정을 돕는 프로그램으로 사용자에 의해 작성됩니다. S3C2440이나 2410은 NAND부트모드와

NOR부트모드가 있습니다(하드웨어 적으로). NOR부트모드에서는 NOR플래시의 0x0번지에 프로그램을 저장해 두면

그 프로그램이 바로 실행됩니다. 하지만 NAND부트모드는 NAND 플래시 메모리가 랜덤액세스가 가능한 메모리가 아니므로

NAND플래시에서 프로그램 실행이 되지 않습니다. 따라서 NAND플래시에 저장된 프로그램을 SDRAM으로 옮겨서

실행해야 하는데 이 과정을 사용자가 직접 구현해 줘야 합니다. 즉 이게 NAND부팅시의 부트코드가 되는것입니다.

실제프로그램을 실행하기 위해 그 프로그램을 로딩해주는 소형의 코드들이 부트코드로 보시면됩니다.

 

NAND부트 모드에서는 부트코드가 꼭 있어야하고 NOR 부트 모드에서는 있어도 되고 없어도 됩니다. 만약에 NOR부트모드에

서 부트코드를 사용한다면 부트코드가 0x0번지에 위치하고 실행될 프로그램은 NOR플래시 메모리 뒷부분에 위치 시켰다가

부팅될 때 부트코드에 의해 실행될 프로그램을 NOR플래시에서 SDRAM으로 옮긴다음 그 프로그램으로 점프하여 실행시킬 수

있습니다. 이렇게 하는 이유는 SDRAM이 액세스속도가 빠르기 때문에 가급적이면 프로그램을 SDRAM에서 실생시키기 위해

서 이고 부트코드에 의해 본 프로그램을 업데이트 하기 위해서도 사용합니다. 매번 JTAG장비로 NOR플래시에 writing할 수 없

으니 제품을 생산한 후에 부트코드에 의해 펌웨어를 업데이트 시키는 방법도 있습니다.

 
  부트코드에도 startup 코드가 포함됩니다. 부팅을 원하는 형태로 진행하기 위한 코드이므로 어차피 사용자 프로그램이나

마찬가지입니다. 따라서 기본적인 설정에 필요한 startup코드가 포함되어야 합니다. 다만 간단한 부트코드들은 startup코드

상에서 다 구현하기도 합니다.

아쉽게도 JSAPI(Java Speech API)에 관한 책은 외국에도 국내에도 출간된 적이 없는 걸로 알고 있습니다.
책이 출간될만한 소재도 아니구요. 아래 글에 나와있는 링크사이트들을 참조하시고  검색엔진 검색(구글, 네이버 등)을 해보시기 바랍니다.
http://www.javastudy.co.kr/javastudy/new_bbs/qna_view.jsp?pageNum=1&find_method=&find_key=&bbs_name=qajavabbs&theid=46300

출처 : http://cseric.cau.ac.kr/new_Cseric/yungoostep/content.asp?idx=634&page=1
JSAPI (Java Speech API)

내용

음성 기술의 발달로 응용 프로그램 개발자와 사용자들의 음성 기술 접근에 대한 요구가 증가함에 따라 음성 관련 API들이 등장하기에 이르렀다. 이에 대응하여 Java 진영에서도 Speech 관련 API를 개발하여 JSAPI(Java Speech API)라는 이름으로 배포하게 되었다. JSAPI는 JDK에 포함되어 있지 않으며 SUN사에서도 배포하지 않는다. 이를 얻기 위해서는 서드 파티의 다른 회사들의 홈페이지에서 얻어야 한다. 대표적으로 SourceForge에 있는 FreeTTS가 있다.
보통 음성 기술이 지원되는 응용프로그램은 오디오 하드웨어와 직접 상호작용하지는 않는다. 대신 음성 엔진(Speech Engine)이라는 공통 응용이 중간에서 조정자 역할을 한다. 각 벤더에 의해 구현된 음성 엔진은 벤더들의 방식에 따라 엔진에 접근할 수 응용 프로그램 인터페이스를 제공한다. JSAPI는 모든 플랫폼과 벤더에 독립적이다. JSAPI는 음성 응용 프로그램이 표준화되고, 일상적이며, 구현으로부터 독립적인 방식으로 음성 엔진과 상호작용한다. 즉, 음성엔진이 JSAPI와 호환된다면, JSAPI를 통해 여러 다른 벤더의 음성 엔진에 접근할 수 있는 것이다.
JSAPI를 가지고 음성 응용 프로그램은 특정 언어나 목소리 등을 선택하는데 음성 엔진을 사용할 수 있다. JSAPI는 음성 기술의 큰 두 줄기인 음성 합성과 음성 인식을 모두 제공한다.


위의 그림은 JSAPI의 스택을 보여준다. 스택의 맨아래인 음성 엔진은 실제 오디오 하드웨어와 상호작용하며, 맨 위의 JSAPI 응용은 표준화되고 일관된 방법으로 음성 엔진에 의한 음성 합성, 음성 인식 기능을 사용할 수 있도록 제공한다. 많은 음성 엔진들이 JSAPI와 호환되며 상용 또는 무료로 배포되고 있다. 무료 음성 엔진으로는 Festival speech synthesis system이 유명하다.

참고사이트

JSAPI 홈페이지
http://java.sun.com/products/java-media/speech/index.jsp

FreeTTS
http://freetts.sourceforge.net/

Festival
http://www.cstr.ed.ac.uk/projects/festival/





소켓프로그램에 대해 공부하였다. 자세히 들어가 공부하는 것 아니지만 서버랑 클라이언트랑 가위바위 보를 하는 프로그램을 통하여 소켓의 생성원리, fork()함수, pipe()함수에 대해 다뤄보는 소스를 분석해보자.

일단 소켓을 무엇인지 알아야 소켓을 생성를 하지 않겠는가. 난 처음에 소켓을 하나의 패킷이라고 생각했지만 그런 개념을 아니였다. 서로 멀리 떨어져 있는 매개체를 연결해주는 역활을 해야된다고 생각해야되나..? 하여튼 그런 개념을 소켓이라고 한다. 자 그럼 한번 소스를 봐볼까

------------------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>

#define BUFSIZE 100
void error_handling(char *message);
void z_handler(int sig);
int who_win(int a, int b);
------------------------------------------------------------------------------------------
여기까지는 함수를 사용할 헤더파일 정의 또한 밑에서 사용할 사용자 정의 함수를 각각 선언하였다.

-------------------------------------------------------------------------------------------
int
main(int argc, char **argv)
{
int fd1[2], fd2[2];

char buffer[BUFSIZE];
char intro[]="Input(gawi : 0, bawi : 1, bo : 2) : ";
char win[] = "You Win!!\n";
char lose[] = "You Lose!!\n";
char no_winner[] = "Oh same!! Re try!!\n";

int serv_sock;
int clnt_sock;
struct sockaddr_in serv_addr;
struct sockaddr_in clnt_addr;
struct sigaction act;
int str_len, state, addr_size;
pid_t pid;
---------------------------------------------------------------------------------------------
이부분은 각각 사용할 변수와 구조체를 선언하였다. 맨 마지막에 형이 없이 pid_t를 선언한 부분이 있는데 이걸 사용자 정의 변수라 한다. 사용자가 알아보기 싶게할때 쓰거나 만약 int형이 시스템 마다 틀려서 define해서 쓸수 있게 하여 확장성 높일때 사용한다.

-------------------------------------------------------------------------------------------
if( argc != 2 )
{
printf("Usage : %s <port>\n", argv[0]);
exit(1);
}
-------------------------------------------------------------------------------------------
이 프로그램은 서버 프로그램이다. 서버프로그램은 실행파일명 하고 뒤에 클라이언트와 접속할수 있는 포트 번호를 써줘야 하기때문에 인수가 2가 아니면 포트를 사용하라고 에러문이 뜨게 한다.

-------------------------------------------------------------------------------------------
if( pipe(fd1) < 0 || pipe(fd2) < 0 ) error_handling("pipe() error!");
-------------------------------------------------------------------------------------------
파이프 함수를 정의 하여 사용한다. 만약 파이프 함수가 에러가 나면 -1값을 리턴하는데 이때 오류문을 출력하는 구문

------------------------------------------------------------------------------------------
act.sa_hander = z_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
state = sigaction(SIGCHLD, &act, 0);
if( state != 0 ) error_handling("sigaction() error");
-------------------------------------------------------------------------------------------
struct sigaction{
void (*sa_handler) int /* 취해질 행동 */
sigset_t sa_mask /*시그널을 처리할 동안 추가의 시그널을 봉쇄 */
int sa_flags /*시그널을 형태에 영향을 미칠 플래그들 */
void(*sa_sigaction ) (int, siginfo_t *, vodi *) /* 시그널 핸들러에 대한 포인터 */

시그널 구조체에 각각의 값을 넣는 구문이다. 두번째 sigemptyset()는 초기화 하란 뜻이다. SIGCHLD는 자식프로세스의 신호에 대한 값으로 시스템에서 SIGCHLD가 발생이 되면 &act에 걸린 핸들러를 호출하는 구문이다.


---------------------------------------------------------------------------------------------
serv_sock = socket(PF_INET, SOCK_STREAM, 0);
---------------------------------------------------------------------------------------------
스트림형 소켓(TCP통신)을 생성한다.

-------------------------------------------------------------------------------------------
memset(&serv_addr, 0, sizeof(serv_addr));
-------------------------------------------------------------------------------------------
serv_addr주소 부터 serv_addr 주소크기까지 0으로 채운라는 뜻이다 즉 초기화시키는 뜻을 가지고 있다.

------------------------------------------------------------------------------------------
serv_addr.sin_family = AF_INET;
-------------------------------------------------------------------------------------------
아아피 버전4 주소를 사용하겠다는의미

-------------------------------------------------------------------------------------------
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
-------------------------------------------------------------------------------------------
htonl ->호스트의 네트워크 바이트 순서를 32비트를 사용하겠다는 의미 리틀 엔디안과 빅 엔디안의 차이 즉 CPU계열에 메모리 저장방식이 서로 틀려도 이것에 상관없이 사용할수 있도록 한다. (INADDR_ANY)자기 아이피 주소할당

-----------------------------------------------------------------------------------------
serv_addr.sin_port = htons(atoi(argv[1]));
-----------------------------------------------------------------------------------------
htons ->포트정보를 바꿔주겠단 의미로써 16-비트 정수로 된 호스트 바이트 오더를 네트웍 바이트 오더로 변환하는 함수이다. htons 함수는 SOCKADDR_IN 구조체에 저장되기 전에 포트 번호를 네트웍 바이트 오더로 변환하는데 자주 사용 한다

-------------------------------------------------------------------------------------------
if( bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) )
error_handling("bind() error");
--------------------------------------------------------------------------------------------
bind 소켓에다 주소를 할당 해주는 함수
ipv4에 할당된 주소를 표준된 주소로 형변환 할려는 것

-------------------------------------------------------------------------------------------
if( listen(serv_sock, 5)) error_handling("listen() error");
-------------------------------------------------------------------------------------------
listen 소켓연결 요청 대기 상태 5는 큐의 크기(클라이언트가 여러명들어갈수 있게

-------------------------------------------------------------------------------------------
while(1)
{
addr_size = sizeof(clnt_addr);

clnt_sock = accept(serv_sock, (struct sockaddr*) &clnt_addr, &addr_size);
if( clnt_sock == -1 ) continue;
-------------------------------------------------------------------------------------------
연결요청이 들어오면 받아들이는 함수(또하나의 소켓을 만들어준다. 클라인트 접속한 정보들이 구조체에 채워지고 에러가 나면 다시 처음으로 돌아간다.

-----------------------------------------------------------------------------------------
if( (pid = fork()) == -1 )
{
close(clnt_sock);
continue;
}
------------------------------------------------------------------------------------------
자식 프로세스 생성하다 오류나면 반복문 처음으로 돌아감

------------------------------------------------------------------------------------------
else if( pid > 0 )
{
int result;
puts("connection success");

close(clnt_sock);
//클라이언트 소켓을 닫아준다
//나중에 자식프로세스가 닫아주면 완전히 닫혀진다. (부모가 미리 닫는다.)

write(1, intro, sizeof(intro));
//첫번재 인수는 파일디스크립트(파일티스크립트는 시스템이 할당받은 미리 정해진 일련번호 라고 생각하면 된다. 보통 0은 표준입력 1은 표준출력 2는 표준에러를 뜻한다),intro 출력하라는 의미

read(0, buffer, BUFSIZE);
//사용자가 가위,바위,보를 저장한다.

read(fd1[0], &buffer[1], BUFSIZE - 1);
//클라이언트 가위바위보 낸걸 fd1[1]에서 서버 fd1[0]으로 읽어온다(파이브 함수를 통해서).

result = who_win(buffer[0], buffer[1]);
//buffer[0]에 서버 , buffer[1]에 클라이언트

if( result == 0 )
{
write(1, no_winner, sizeof(no_winner));
write(fd2[1], no_winner, sizeof(no_winner));
}
else if( result == 1 )
{
write(1, win, sizeof(win));
write(fd2[1], lose, sizeof(lose));
}
else
{
write(1, lose, sizeof(lose));
write(fd2[1], win, sizeof(win));
}
//이겼는지 졌는지 비겼는지를 출력하는 조건문이다.
}
--------------------------------------------------------------------------------------------
부모프로세스가 해야할것

---------------------------------------------------------------------------------------------
else
{
close(serv_sock);

write(clnt_sock, intro, sizeof(intro));
read(clnt_sock, buffer, BUFSIZE);
write(fd1[1], buffer, 1);
str_len = read(fd2[0], buffer, BUFSIZE);

write(clnt_sock, buffer, str_len);

puts("connection end");
close(clnt_sock);
exit(0);
}
----------------------------------------------------------------------------------------------
자식프로세스는 클라이언트에게 서버가 낸 가위바위보 정보를 전달해주는 역활을 한다.


}
return 0;
}

---------------------------------------------------------------------------------------------
void
z_handler(int sig)
{
pid_t pid;
int rtn;

pid = waitpid(-1, &rtn, WNOHANG);
//waitpid는 프로세스의 번호를 받는다. 첫번째 인자는 어떤프로세스에게 pid를 받을지 쓴다.
//(-1는 기달렸다가 먼저 종료되는 프로세스를 이미로 받는다.
//셋번째인자는 기달려도 종료된 자식프로세스가 신호를 않보내면 자동적으로 종료

printf("killed zombie pid : %d \n", pid);
printf("returned data : %d \n\n", WEXITSTATUS(rtn));
//자식프로세스가 죽었다는 신호(숫자)를 리턴값으로 전달해주는 함수
}
-------------------------------------------------------------------------------------------
자식프로세스 신호의 핸드러에 관한 함수이다.

-------------------------------------------------------------------------------------------
int
who_win(int a, int b)
{
if( a == b ) return 0;

else if( a % 3 == (b + 1) % 3) return 1;
//서버가 이길경우

else return -1;
//클라이언트가 이길 경우
}
---------------------------------------------------------------------------------------------
클라이언트와 서버간에 가위바위보 비교

--------------------------------------------------------------------------------------------
void
error_handling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
---------------------------------------------------------------------------------------------
에러문 출력


Cross Compiler는 컴파일러가 생성하는 오브젝트 코드가 컴파일러가 구동되는 시스템의 오브젝트 코드가 아닌 경우를 말합니다. 이를테면, 인텔i386 아키텍처 머신인 PC에서 ARM 기반의 머신인 PDA등에서 돌아가는 프로그램을 컴파일한다고 할때, 이때 i386에서 구동되는 ARM컴파일러가 필요합니다. 이것이 크로스 컴파일러입니다.
따라서 크로스 컴파일러로 생성된 코드는 다른 기기로 옮겨서 작동하는 것을 전제로 하는 컴파일러를 말합니다. 따라서 컴파일이 이루어지는 시스템에서는 작동하지 않는 것이 자연스러운 귀결입니다.

Native Compiler는 컴파일러가 생성하는 오브젝트 코드가 컴파일러가 구동되는 시스템의 오브젝트 코드인 경우를 말합니다. 컴파일이 이루어지는 시스템에서 그대로 생성된 오브젝트 코드를 실행할 수 있다면 Native Compiler라고 부릅니다.

임의의 Directed Graph 가 주어졌을 때, 시작점 S에서 끝점 E까지 흐를 수 있는 최대 유량을 구하는 Algorithm.

Network Flow(Maximum Flow) 를 해결하는 방법 중 하나로 Ford-Fulkerson 알고리즘이 있다.

Ford-Fulkerson 알고리즘 :
시작점 -> 끝점까지 하나의 경로를 찾는다. (이 때 BFS로 찾아 간선수를 최소로 해야 효율적임 : Edmond-Karp Algorithm)
경로 중 가중치가 최소인 간선을 찾아 아까 찾은 경로의 정방향에서 빼주고 역방향에서 더해준다.
(이것은 정방향으로 일정한 유량을 흘리고 흘릴 수 있는 가중치를 다시 계산해주는 과정이다.)
유량 그래프 역시 갱신해준다.
더 이상 경로를 찾을 수 없을 때까지 위의 과정을 반복한다.

=> Network Flow 알고리즘의 응용으로 Bipartite Matching(이분 매칭) 문제를 해결 할 수 있다.

임의의 시작점 s를 만들어 이분 매칭의 한쪽 집합을 모두 연결한다. (모든 가중치 1)
Matching 가능한 두 원소를 가중치 1인 Edge로 연결한다.
임의의 끝점 e를 만들어 다른쪽 집합을 모두 연결한다. (가중치 1)

이 그래프에 대하여 Network Flow를 실행한다.
이 때의 Flow가 최대 이분 매칭 쌍의 수이다.

=> 제거되는 그래프 간선의 가중치의 합을 최소로 하여 그래프를 두 부분으로 분리하는 Minimum Cut 문제 역시 전체 간선 가중치의 합에서 Maximum Flow를 제거하면 된다는 것이 증명되어 있다.

+ Recent posts